Index: trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 16187)
@@ -592,9 +592,9 @@
             // revert all executed commands
             ds = executedCmds.getFirst().getAffectedDataSet();
-            ds.beginUpdate();
-            while (!executedCmds.isEmpty()) {
-                executedCmds.removeLast().undoCommand();
-            }
-            ds.endUpdate();
+            ds.update(() -> {
+                while (!executedCmds.isEmpty()) {
+                    executedCmds.removeLast().undoCommand();
+                }
+            });
         }
     }
@@ -1748,15 +1748,10 @@
         @Override
         public void undoCommand() {
-            getAffectedDataSet().beginUpdate();
-            super.undoCommand();
-            getAffectedDataSet().endUpdate();
+            getAffectedDataSet().update(super::undoCommand);
         }
 
         @Override
         public boolean executeCommand() {
-            getAffectedDataSet().beginUpdate();
-            boolean rc = super.executeCommand();
-            getAffectedDataSet().endUpdate();
-            return rc;
+            return getAffectedDataSet().update(super::executeCommand);
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/MoveAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/MoveAction.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/actions/MoveAction.java	(revision 16187)
@@ -12,5 +12,4 @@
 import javax.swing.JOptionPane;
 
-import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.MoveCommand;
 import org.openstreetmap.josm.data.UndoRedoHandler;
@@ -98,15 +97,10 @@
     }
 
-    @Override
-    public void actionPerformed(ActionEvent event) {
-        DataSet ds = getLayerManager().getEditDataSet();
-
-        if (!MainApplication.isDisplayingMapView() || ds == null)
-            return;
-
-        // find out how many "real" units the objects have to be moved in order to
-        // achive an 1-pixel movement
-
-        MapView mapView = MainApplication.getMap().mapView;
+    /**
+     * Find out how many "real" units the objects have to be moved in order to achieve an 1-pixel movement
+     * @param mapView map view
+     * @return move offset
+     */
+    private EastNorth getOffset(MapView mapView) {
         EastNorth en1 = mapView.getEastNorth(100, 100);
         EastNorth en2 = mapView.getEastNorth(101, 101);
@@ -131,26 +125,37 @@
         }
 
+        return new EastNorth(distx, disty);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent event) {
+        DataSet ds = getLayerManager().getEditDataSet();
+
+        if (!MainApplication.isDisplayingMapView() || ds == null)
+            return;
+
+        MapView mapView = MainApplication.getMap().mapView;
+        final EastNorth dist = getOffset(mapView);
+
         Collection<OsmPrimitive> selection = ds.getSelected();
         Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
 
-        Command c = UndoRedoHandler.getInstance().getLastCommand();
-
-        ds.beginUpdate();
-        try {
+        MoveCommand cmd = ds.update(c -> {
+            MoveCommand moveCmd;
             if (c instanceof MoveCommand && ds.equals(c.getAffectedDataSet())
                     && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
-                ((MoveCommand) c).moveAgain(distx, disty);
+                moveCmd = (MoveCommand) c;
+                moveCmd.moveAgain(dist.east(), dist.north());
             } else {
-                c = new MoveCommand(ds, selection, distx, disty);
-                UndoRedoHandler.getInstance().add(c);
+                moveCmd = new MoveCommand(ds, selection, dist.east(), dist.north());
+                UndoRedoHandler.getInstance().add(moveCmd);
             }
-        } finally {
-            ds.endUpdate();
-        }
+            return moveCmd;
+        }, UndoRedoHandler.getInstance().getLastCommand());
 
         for (Node n : affectedNodes) {
             if (n.isLatLonKnown() && n.isOutSideWorld()) {
                 // Revert move
-                ((MoveCommand) c).moveAgain(-distx, -disty);
+                cmd.moveAgain(-dist.east(), -dist.north());
                 JOptionPane.showMessageDialog(
                         MainApplication.getMainFrame(),
Index: trunk/src/org/openstreetmap/josm/actions/SimplifyWayAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/SimplifyWayAction.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/actions/SimplifyWayAction.java	(revision 16187)
@@ -172,6 +172,5 @@
     public void actionPerformed(ActionEvent e) {
         DataSet ds = getLayerManager().getEditDataSet();
-        ds.beginUpdate();
-        try {
+        ds.update(() -> {
             List<Way> ways = ds.getSelectedWays().stream()
                     .filter(p -> !p.isIncomplete())
@@ -195,7 +194,5 @@
                 simplifyWays(ways, err);
             }
-        } finally {
-            ds.endUpdate();
-        }
+        });
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 16187)
@@ -247,11 +247,8 @@
 
     private static void addRemoveSelection(DataSet ds, OsmPrimitive toAdd, OsmPrimitive toRemove) {
-        ds.beginUpdate(); // to prevent the selection listener to screw around with the state
-        try {
+        ds.update(() -> { // to prevent the selection listener to screw around with the state
             addSelection(ds, toAdd);
             clearSelection(ds, toRemove);
-        } finally {
-            ds.endUpdate();
-        }
+        });
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 16187)
@@ -712,18 +712,19 @@
         if (mode == Mode.MOVE) {
             if (startEN == null) return false; // fix #8128
-            ds.beginUpdate();
-            try {
+            return ds.update(() -> {
+                MoveCommand moveCmd = null;
                 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
-                    ((MoveCommand) c).saveCheckpoint();
-                    ((MoveCommand) c).applyVectorTo(currentEN);
+                    moveCmd = (MoveCommand) c;
+                    moveCmd.saveCheckpoint();
+                    moveCmd.applyVectorTo(currentEN);
                 } else if (!selection.isEmpty()) {
-                    c = new MoveCommand(selection, startEN, currentEN);
-                    UndoRedoHandler.getInstance().add(c);
+                    moveCmd = new MoveCommand(selection, startEN, currentEN);
+                    UndoRedoHandler.getInstance().add(moveCmd);
                 }
                 for (Node n : affectedNodes) {
                     if (n.isOutSideWorld()) {
                         // Revert move
-                        if (c instanceof MoveCommand) {
-                            ((MoveCommand) c).resetToCheckpoint();
+                        if (moveCmd != null) {
+                            moveCmd.resetToCheckpoint();
                         }
                         // TODO: We might use a simple notification in the lower left corner.
@@ -737,7 +738,6 @@
                     }
                 }
-            } finally {
-                ds.endUpdate();
-            }
+                return true;
+            });
         } else {
             startEN = currentEN; // drag can continue after scaling/rotation
@@ -747,6 +747,5 @@
             }
 
-            ds.beginUpdate();
-            try {
+            return ds.update(() -> {
                 if (mode == Mode.ROTATE) {
                     if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand) c).getTransformedNodes())) {
@@ -767,9 +766,7 @@
                     MainApplication.getMap().statusLine.setDist(ways);
                 }
-            } finally {
-                ds.endUpdate();
-            }
-        }
-        return true;
+                return true;
+            });
+        }
     }
 
@@ -910,6 +907,5 @@
             Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
             Command c = getLastCommandInDataset(ds);
-            ds.beginUpdate();
-            try {
+            ds.update(() -> {
                 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
                     Node selectedNode = selNodes.iterator().next();
@@ -919,7 +915,5 @@
                                                 targetEN.getY() - selectedEN.getY());
                 }
-            } finally {
-                ds.endUpdate();
-            }
+            });
         }
 
Index: trunk/src/org/openstreetmap/josm/command/PurgeCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/PurgeCommand.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/command/PurgeCommand.java	(revision 16187)
@@ -84,6 +84,5 @@
     @Override
     public boolean executeCommand() {
-        getAffectedDataSet().beginUpdate();
-        try {
+        getAffectedDataSet().update(() -> {
             purgedConflicts.get().clear();
             // unselect primitives in advance to not fire a selection change for every one of them
@@ -116,7 +115,5 @@
             }
             getAffectedDataSet().clearMappaintCache();
-        } finally {
-            getAffectedDataSet().endUpdate();
-        }
+        });
         return true;
     }
@@ -127,6 +124,5 @@
             return;
 
-        getAffectedDataSet().beginUpdate();
-        try {
+        getAffectedDataSet().update(() -> {
             for (OsmPrimitive osm : toPurge) {
                 PrimitiveData data = makeIncompleteDataByPrimId.get(osm);
@@ -147,7 +143,5 @@
             }
             getAffectedDataSet().clearMappaintCache();
-        } finally {
-            getAffectedDataSet().endUpdate();
-        }
+        });
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 16187)
@@ -24,4 +24,5 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -256,12 +257,9 @@
     public DataSet(OsmPrimitive... osmPrimitives) {
         this();
-        beginUpdate();
-        try {
+        update(() -> {
             for (OsmPrimitive o : osmPrimitives) {
                 addPrimitive(o);
             }
-        } finally {
-            endUpdate();
-        }
+        });
     }
 
@@ -499,6 +497,5 @@
         Objects.requireNonNull(primitive, "primitive");
         checkModifiable();
-        beginUpdate();
-        try {
+        update(() -> {
             if (getPrimitiveById(primitive) != null)
                 throw new DataIntegrityProblemException(
@@ -511,7 +508,5 @@
             store.addPrimitive(primitive);
             firePrimitivesAdded(Collections.singletonList(primitive), false);
-        } finally {
-            endUpdate();
-        }
+        });
     }
 
@@ -528,6 +523,5 @@
     public void removePrimitive(PrimitiveId primitiveId) {
         checkModifiable();
-        beginUpdate();
-        try {
+        update(() -> {
             OsmPrimitive primitive = getPrimitiveByIdChecked(primitiveId);
             if (primitive == null)
@@ -535,7 +529,5 @@
             removePrimitiveImpl(primitive);
             firePrimitivesRemoved(Collections.singletonList(primitive), false);
-        } finally {
-            endUpdate();
-        }
+        });
     }
 
@@ -552,11 +544,8 @@
     void removePrimitive(OsmPrimitive primitive) {
         checkModifiable();
-        beginUpdate();
-        try {
+        update(() -> {
             removePrimitiveImpl(primitive);
             firePrimitivesRemoved(Collections.singletonList(primitive), false);
-        } finally {
-            endUpdate();
-        }
+        });
     }
 
@@ -804,7 +793,6 @@
     public Set<Way> unlinkNodeFromWays(Node node) {
         checkModifiable();
-        Set<Way> result = new HashSet<>();
-        beginUpdate();
-        try {
+        return update(() -> {
+            Set<Way> result = new HashSet<>();
             for (Way way : node.getParentWays()) {
                 List<Node> wayNodes = way.getNodes();
@@ -818,8 +806,6 @@
                 }
             }
-        } finally {
-            endUpdate();
-        }
-        return result;
+            return result;
+        });
     }
 
@@ -833,7 +819,6 @@
     public Set<Relation> unlinkPrimitiveFromRelations(OsmPrimitive primitive) {
         checkModifiable();
-        Set<Relation> result = new HashSet<>();
-        beginUpdate();
-        try {
+        return update(() -> {
+            Set<Relation> result = new HashSet<>();
             for (Relation relation : getRelations()) {
                 List<RelationMember> members = relation.getMembers();
@@ -854,8 +839,6 @@
                 }
             }
-        } finally {
-            endUpdate();
-        }
-        return result;
+            return result;
+        });
     }
 
@@ -869,15 +852,12 @@
     public Set<OsmPrimitive> unlinkReferencesToPrimitive(OsmPrimitive referencedPrimitive) {
         checkModifiable();
-        Set<OsmPrimitive> result = new HashSet<>();
-        beginUpdate();
-        try {
+        return update(() -> {
+            Set<OsmPrimitive> result = new HashSet<>();
             if (referencedPrimitive instanceof Node) {
                 result.addAll(unlinkNodeFromWays((Node) referencedPrimitive));
             }
             result.addAll(unlinkPrimitiveFromRelations(referencedPrimitive));
-        } finally {
-            endUpdate();
-        }
-        return result;
+            return result;
+        });
     }
 
@@ -979,4 +959,52 @@
     }
 
+    /**
+     * Performs the update runnable between {@link #beginUpdate()} / {@link #endUpdate()} calls.
+     * @param runnable update action
+     * @since 16187
+     */
+    public void update(Runnable runnable) {
+        beginUpdate();
+        try {
+            runnable.run();
+        } finally {
+            endUpdate();
+        }
+    }
+
+    /**
+     * Performs the update function between {@link #beginUpdate()} / {@link #endUpdate()} calls.
+     * @param function update function
+     * @param t function argument
+     * @param <T> argument type
+     * @param <R> result type
+     * @return function result
+     * @since 16187
+     */
+    public <T, R> R update(Function<T, R> function, T t) {
+        beginUpdate();
+        try {
+            return function.apply(t);
+        } finally {
+            endUpdate();
+        }
+    }
+
+    /**
+     * Performs the update supplier between {@link #beginUpdate()} / {@link #endUpdate()} calls.
+     * @param supplier update supplier
+     * @param <R> result type
+     * @return supplier result
+     * @since 16187
+     */
+    public <R> R update(Supplier<R> supplier) {
+        beginUpdate();
+        try {
+            return supplier.get();
+        } finally {
+            endUpdate();
+        }
+    }
+
     private void fireEventToListeners(AbstractDatasetChangedEvent event) {
         for (DataSetListener listener : listeners) {
@@ -1044,18 +1072,10 @@
      * Invalidates the internal cache of projected east/north coordinates.
      *
-     * This method can be invoked after the globally configured projection method
-     * changed.
+     * This method can be invoked after the globally configured projection method changed.
      */
     public void invalidateEastNorthCache() {
         if (ProjectionRegistry.getProjection() == null)
             return; // sanity check
-        beginUpdate();
-        try {
-            for (Node n : getNodes()) {
-                n.invalidateEastNorthCache();
-            }
-        } finally {
-            endUpdate();
-        }
+        update(() -> getNodes().forEach(Node::invalidateEastNorthCache));
     }
 
@@ -1064,6 +1084,5 @@
      */
     public void cleanupDeletedPrimitives() {
-        beginUpdate();
-        try {
+        update(() -> {
             Collection<OsmPrimitive> toCleanUp = getPrimitives(
                     primitive -> primitive.isDeleted() && (!primitive.isVisible() || primitive.isNew()));
@@ -1076,7 +1095,5 @@
                 firePrimitivesRemoved(toCleanUp, false);
             }
-        } finally {
-            endUpdate();
-        }
+        });
     }
 
@@ -1091,6 +1108,5 @@
         //TODO: Report listeners that are still active (should be none)
         checkModifiable();
-        beginUpdate();
-        try {
+        update(() -> {
             clearSelection();
             for (OsmPrimitive primitive : allPrimitives) {
@@ -1099,7 +1115,5 @@
             store.clear();
             allPrimitives.clear();
-        } finally {
-            endUpdate();
-        }
+        });
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 16187)
@@ -424,6 +424,5 @@
             progressMonitor.beginTask(tr("Merging data..."), sourceDataSet.allPrimitives().size());
         }
-        targetDataSet.beginUpdate();
-        try {
+        targetDataSet.update(() -> {
             List<? extends OsmPrimitive> candidates = new ArrayList<>(targetDataSet.getNodes());
             for (Node node: sourceDataSet.getNodes()) {
@@ -481,7 +480,5 @@
                 targetDataSet.lock();
             }
-        } finally {
-            targetDataSet.endUpdate();
-        }
+        });
         if (progressMonitor != null) {
             progressMonitor.finishTask();
Index: trunk/src/org/openstreetmap/josm/data/osm/FilterModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/FilterModel.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/data/osm/FilterModel.java	(revision 16187)
@@ -110,5 +110,4 @@
             ds.beginUpdate();
             try {
-
                 final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
 
@@ -158,6 +157,5 @@
         List<OsmPrimitive> deselect = new ArrayList<>();
 
-        ds.beginUpdate();
-        try {
+        ds.update(() -> {
             for (int i = 0; i < 2; i++) {
                 for (OsmPrimitive primitive: primitives) {
@@ -190,7 +188,5 @@
                 }
             }
-        } finally {
-            ds.endUpdate();
-        }
+        });
 
         if (!deselect.isEmpty()) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 16187)
@@ -694,13 +694,10 @@
          */
         private void tryUndo() {
-            final DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
-            int i = fixCommands.size() - 1;
-            ds.beginUpdate();
-            for (; i >= 0; i--) {
-                fixCommands.get(i).undoCommand();
-            }
-            ds.endUpdate();
-        }
-
+            MainApplication.getLayerManager().getActiveDataSet().update(() -> {
+                for (int i = fixCommands.size() - 1; i >= 0; i--) {
+                    fixCommands.get(i).undoCommand();
+                }
+            });
+        }
     }
 
@@ -723,15 +720,10 @@
         @Override
         public void undoCommand() {
-            getAffectedDataSet().beginUpdate();
-            super.undoCommand();
-            getAffectedDataSet().endUpdate();
+            getAffectedDataSet().update(super::undoCommand);
         }
 
         @Override
         public boolean executeCommand() {
-            getAffectedDataSet().beginUpdate();
-            boolean rc = super.executeCommand();
-            getAffectedDataSet().endUpdate();
-            return rc;
+            return getAffectedDataSet().update(super::executeCommand);
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 16186)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 16187)
@@ -652,6 +652,5 @@
         // if uploaded, clean the modified flags as well
         data.cleanupDeletedPrimitives();
-        data.beginUpdate();
-        try {
+        data.update(() -> {
             for (OsmPrimitive p: data.allPrimitives()) {
                 if (processed.contains(p)) {
@@ -659,7 +658,5 @@
                 }
             }
-        } finally {
-            data.endUpdate();
-        }
+        });
     }
 
