Index: src/org/openstreetmap/josm/Main.java
===================================================================
--- src/org/openstreetmap/josm/Main.java	(revision 12702)
+++ src/org/openstreetmap/josm/Main.java	(working copy)
@@ -136,7 +136,7 @@
     /**
      * The commands undo/redo handler.
      */
-    public final UndoRedoHandler undoRedo = MainApplication.undoRedo;
+    public final UndoRedoHandler undoRedo = new UndoRedoHandler();
 
     /**
      * The main menu bar at top of screen.
@@ -629,13 +629,27 @@
     }
 
     /**
-     * Gets the data set of the active edit layer.
-     * @return That data set, <code>null</code> if there is no edit layer.
+     * Gets the active edit data set.
+     * @return That data set, <code>null</code>.
      * @since 12691
      */
-    public DataSet getEditDataSet() {
-        return null;
-    }
+    public abstract DataSet getEditDataSet();
+
+    /**
+     * Sets the active data set.
+     * @param ds New edit data set, or <code>null</code>
+     * @since xxx
+     */
+    public abstract void setEditDataSet(DataSet ds);
+
+    /**
+     * Determines if the list of data sets managed by JOSM contains {@code ds}.
+     *
+     * @param ds the data set to look for
+     * @return {@code true} if the list of data sets managed by JOSM contains {@code ds}
+     * @since xxx
+     */
+    public abstract boolean containsDataSet(DataSet ds);
 
     /**
      * Registers a {@code JosmAction} and its shortcut.
Index: src/org/openstreetmap/josm/actions/JoinAreasAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/JoinAreasAction.java	(working copy)
@@ -692,7 +692,7 @@
 
         // Delete the discarded inner ways
         if (!discardedWays.isEmpty()) {
-            Command deleteCmd = DeleteCommand.delete(getLayerManager().getEditLayer(), discardedWays, true);
+            Command deleteCmd = DeleteCommand.delete(discardedWays, true);
             if (deleteCmd != null) {
                 cmds.add(deleteCmd);
                 commitCommands(marktr("Delete Ways that are not part of an inner multipolygon"));
@@ -1017,7 +1017,7 @@
         List<List<Node>> chunks = buildNodeChunks(way, nodes);
 
         if (chunks.size() > 1) {
-            SplitWayResult split = SplitWayAction.splitWay(getLayerManager().getEditLayer(), way, chunks,
+            SplitWayResult split = SplitWayAction.splitWay(way, chunks,
                     Collections.<OsmPrimitive>emptyList(), SplitWayAction.Strategy.keepFirstChunk());
 
             if (split != null) {
@@ -1466,7 +1466,7 @@
         for (Way w : inner) {
             newRel.addMember(new RelationMember("inner", w));
         }
-        cmds.add(layer != null ? new AddCommand(layer, newRel) :
+        cmds.add(layer != null ? new AddCommand(layer.data, newRel) :
             new AddCommand(inner.iterator().next().getDataSet(), newRel));
         addedRelations.add(newRel);
 
@@ -1537,7 +1537,6 @@
             cmds.add(new ChangeCommand(r.rel, newRel));
         }
 
-        OsmDataLayer layer = getLayerManager().getEditLayer();
         Relation newRel;
         switch (multiouters.size()) {
         case 0:
@@ -1566,7 +1565,7 @@
                 relationsToDelete.add(r.rel);
             }
             newRel.addMember(new RelationMember("outer", outer));
-            cmds.add(layer != null ? new AddCommand(layer, newRel) : new AddCommand(outer.getDataSet(), newRel));
+            cmds.add(new AddCommand(outer.getDataSet(), newRel));
         }
     }
 
Index: src/org/openstreetmap/josm/actions/PurgeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/PurgeAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/PurgeAction.java	(working copy)
@@ -117,7 +117,7 @@
     public PurgeCommand getPurgeCommand(Collection<OsmPrimitive> sel) {
         layer = getLayerManager().getEditLayer();
         toPurgeAdditionally = new ArrayList<>();
-        PurgeCommand cmd = PurgeCommand.build(layer, sel, toPurgeAdditionally);
+        PurgeCommand cmd = PurgeCommand.build(sel, toPurgeAdditionally);
         modified = cmd.getParticipatingPrimitives().stream().anyMatch(OsmPrimitive::isModified);
         return cmd;
     }
Index: src/org/openstreetmap/josm/actions/RedoAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/RedoAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/RedoAction.java	(working copy)
@@ -8,9 +8,9 @@
 import java.awt.event.KeyEvent;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Shortcut;
 
 /**
@@ -18,7 +18,7 @@
  *
  * @author imi
  */
-public class RedoAction extends JosmAction implements OsmDataLayer.CommandQueueListener {
+public class RedoAction extends JosmAction implements CommandQueueListener {
 
     /**
      * Construct the action with "Redo" as label.
Index: src/org/openstreetmap/josm/actions/SplitWayAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/SplitWayAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/SplitWayAction.java	(working copy)
@@ -213,7 +213,7 @@
                 }
             }
             if (wayToKeep != null) {
-                final SplitWayResult result = doSplitWay(getLayerManager().getEditLayer(), selectedWay, wayToKeep, newWays, sel);
+                final SplitWayResult result = doSplitWay(selectedWay, wayToKeep, newWays, sel);
                 MainApplication.undoRedo.add(result.getCommand());
                 if (!result.getNewSelection().isEmpty()) {
                     getLayerManager().getEditDataSet().setSelected(result.getNewSelection());
@@ -293,8 +293,7 @@
             super.buttonAction(buttonIndex, evt);
             toggleSaveState(); // necessary since #showDialog() does not handle it due to the non-modal dialog
             if (getValue() == 1) {
-                SplitWayResult result = doSplitWay(MainApplication.getLayerManager().getEditLayer(),
-                        selectedWay, list.getSelectedValue(), newWays, selection);
+                SplitWayResult result = doSplitWay(selectedWay, list.getSelectedValue(), newWays, selection);
                 MainApplication.undoRedo.add(result.getCommand());
                 if (!result.getNewSelection().isEmpty()) {
                     MainApplication.getLayerManager().getEditDataSet().setSelected(result.getNewSelection());
@@ -497,10 +496,31 @@
      * @param wayChunks the list of way chunks into the way is split. Must not be null.
      * @param selection The list of currently selected primitives
      * @return the result from the split operation
+     * @deprecated to be removed end of 2017. Use {@link #splitWay(Way, List, Collection)} instead
      */
+    @Deprecated
     public static SplitWayResult splitWay(OsmDataLayer layer, Way way, List<List<Node>> wayChunks,
             Collection<? extends OsmPrimitive> selection) {
-        return splitWay(layer, way, wayChunks, selection, Strategy.keepLongestChunk());
+        return splitWay(way, wayChunks, selection);
+    }
+
+    /**
+     * Splits the way {@code way} into chunks of {@code wayChunks} and replies
+     * the result of this process in an instance of {@link SplitWayResult}.
+     *
+     * Note that changes are not applied to the data yet. You have to
+     * submit the command in {@link SplitWayResult#getCommand()} first,
+     * i.e. {@code Main.main.undoredo.add(result.getCommand())}.
+     *
+     * @param way the way to split. Must not be null.
+     * @param wayChunks the list of way chunks into the way is split. Must not be null.
+     * @param selection The list of currently selected primitives
+     * @return the result from the split operation
+     * @since xxx
+     */
+    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks,
+            Collection<? extends OsmPrimitive> selection) {
+        return splitWay(way, wayChunks, selection, Strategy.keepLongestChunk());
     }
 
     /**
@@ -520,9 +540,33 @@
      * @param splitStrategy The strategy used to determine which way chunk should reuse the old id and its history
      * @return the result from the split operation
      * @since 8954
+     * @deprecated to be removed end of 2017. Use {@link #splitWay(Way, List, Collection, Strategy)} instead
      */
+    @Deprecated
     public static SplitWayResult splitWay(OsmDataLayer layer, Way way, List<List<Node>> wayChunks,
             Collection<? extends OsmPrimitive> selection, Strategy splitStrategy) {
+        return splitWay(way, wayChunks, selection, splitStrategy);
+    }
+
+    /**
+     * Splits the way {@code way} into chunks of {@code wayChunks} and replies
+     * the result of this process in an instance of {@link SplitWayResult}.
+     * The {@link org.openstreetmap.josm.actions.SplitWayAction.Strategy} is used to determine which
+     * way chunk should reuse the old id and its history.
+     *
+     * Note that changes are not applied to the data yet. You have to
+     * submit the command in {@link SplitWayResult#getCommand()} first,
+     * i.e. {@code Main.main.undoredo.add(result.getCommand())}.
+     *
+     * @param way the way to split. Must not be null.
+     * @param wayChunks the list of way chunks into the way is split. Must not be null.
+     * @param selection The list of currently selected primitives
+     * @param splitStrategy The strategy used to determine which way chunk should reuse the old id and its history
+     * @return the result from the split operation
+     * @since xxx
+     */
+    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks,
+            Collection<? extends OsmPrimitive> selection, Strategy splitStrategy) {
         // build a list of commands, and also a new selection list
         final List<OsmPrimitive> newSelection = new ArrayList<>(selection.size() + wayChunks.size());
         newSelection.addAll(selection);
@@ -533,11 +577,10 @@
         // Determine which part reuses the existing way
         final Way wayToKeep = splitStrategy.determineWayToKeep(newWays);
 
-        return wayToKeep != null ? doSplitWay(layer, way, wayToKeep, newWays, newSelection) : null;
+        return wayToKeep != null ? doSplitWay(way, wayToKeep, newWays, newSelection) : null;
     }
 
-    static SplitWayResult doSplitWay(OsmDataLayer layer, Way way, Way wayToKeep, List<Way> newWays,
-                                   List<OsmPrimitive> newSelection) {
+    static SplitWayResult doSplitWay(Way way, Way wayToKeep, List<Way> newWays, List<OsmPrimitive> newSelection) {
 
         Collection<Command> commandList = new ArrayList<>(newWays.size());
         Collection<String> nowarnroles = Main.pref.getCollection("way.split.roles.nowarn",
@@ -549,7 +592,7 @@
         // Change the original way
         final Way changedWay = new Way(way);
         changedWay.setNodes(wayToKeep.getNodes());
-        commandList.add(layer != null ? new ChangeCommand(layer, way, changedWay) : new ChangeCommand(way.getDataSet(), way, changedWay));
+        commandList.add(new ChangeCommand(way.getDataSet(), way, changedWay));
         if (!isMapModeDraw && !newSelection.contains(way)) {
             newSelection.add(way);
         }
@@ -560,7 +603,7 @@
             newSelection.addAll(newWays);
         }
         for (Way wayToAdd : newWays) {
-            commandList.add(layer != null ? new AddCommand(layer, wayToAdd) : new AddCommand(way.getDataSet(), wayToAdd));
+            commandList.add(new AddCommand(way.getDataSet(), wayToAdd));
         }
 
         boolean warnmerole = false;
@@ -687,7 +730,7 @@
             }
 
             if (c != null) {
-                commandList.add(layer != null ? new ChangeCommand(layer, r, c) : new ChangeCommand(r.getDataSet(), r, c));
+                commandList.add(new ChangeCommand(r.getDataSet(), r, c));
             }
         }
         if (warnmerole) {
@@ -740,10 +783,32 @@
      * @param atNodes the list of nodes where the way is split. Must not be null.
      * @param selection The list of currently selected primitives
      * @return the result from the split operation
+     * @deprecated to be removed end of 2017. Use {@link #split(Way, List, Collection) instead}
      */
+    @Deprecated
     public static SplitWayResult split(OsmDataLayer layer, Way way, List<Node> atNodes, Collection<? extends OsmPrimitive> selection) {
+        return split(way, atNodes, selection);
+    }
+
+    /**
+     * Splits the way {@code way} at the nodes in {@code atNodes} and replies
+     * the result of this process in an instance of {@link SplitWayResult}.
+     *
+     * Note that changes are not applied to the data yet. You have to
+     * submit the command in {@link SplitWayResult#getCommand()} first,
+     * i.e. {@code Main.main.undoredo.add(result.getCommand())}.
+     *
+     * Replies null if the way couldn't be split at the given nodes.
+     *
+     * @param way the way to split. Must not be null.
+     * @param atNodes the list of nodes where the way is split. Must not be null.
+     * @param selection The list of currently selected primitives
+     * @return the result from the split operation
+     * @since xxx
+     */
+    public static SplitWayResult split(Way way, List<Node> atNodes, Collection<? extends OsmPrimitive> selection) {
         List<List<Node>> chunks = buildSplitChunks(way, atNodes);
-        return chunks != null ? splitWay(layer, way, chunks, selection) : null;
+        return chunks != null ? splitWay(way, chunks, selection) : null;
     }
 
     @Override
Index: src/org/openstreetmap/josm/actions/UndoAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/UndoAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/UndoAction.java	(working copy)
@@ -8,9 +8,9 @@
 import java.awt.event.KeyEvent;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Shortcut;
 
 /**
@@ -18,7 +18,7 @@
  *
  * @author imi
  */
-public class UndoAction extends JosmAction implements OsmDataLayer.CommandQueueListener {
+public class UndoAction extends JosmAction implements CommandQueueListener {
 
     /**
      * Construct the action with "Undo" as label.
Index: src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(working copy)
@@ -150,9 +150,9 @@
 
         Command c;
         if (ctrl) {
-            c = DeleteCommand.deleteWithReferences(editLayer, lm.getEditDataSet().getSelected());
+            c = DeleteCommand.deleteWithReferences(lm.getEditDataSet().getSelected());
         } else {
-            c = DeleteCommand.delete(editLayer, lm.getEditDataSet().getSelected(), !alt /* also delete nodes in way */);
+            c = DeleteCommand.delete(lm.getEditDataSet().getSelected(), !alt /* also delete nodes in way */);
         }
         // if c is null, an error occurred or the user aborted. Don't do anything in that case.
         if (c != null) {
@@ -351,7 +351,7 @@
         CheckParameterUtil.ensureParameterNotNull(layer, "layer");
         CheckParameterUtil.ensureParameterNotNull(toDelete, "toDelete");
 
-        final Command cmd = DeleteCommand.delete(layer, toDelete);
+        final Command cmd = DeleteCommand.delete(toDelete);
         if (cmd != null) {
             // cmd can be null if the user cancels dialogs DialogCommand displays
             MainApplication.undoRedo.add(cmd);
@@ -403,20 +403,19 @@
      */
     private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean silent) {
         DeleteParameters parameters = getDeleteParameters(e, modifiers);
-        OsmDataLayer editLayer = getLayerManager().getEditLayer();
         switch (parameters.mode) {
         case node:
-            return DeleteCommand.delete(editLayer, Collections.singleton(parameters.nearestNode), false, silent);
+            return DeleteCommand.delete(Collections.singleton(parameters.nearestNode), false, silent);
         case node_with_references:
-            return DeleteCommand.deleteWithReferences(editLayer, Collections.singleton(parameters.nearestNode), silent);
+            return DeleteCommand.deleteWithReferences(Collections.singleton(parameters.nearestNode), silent);
         case segment:
-            return DeleteCommand.deleteWaySegment(editLayer, parameters.nearestSegment);
+            return DeleteCommand.deleteWaySegment(parameters.nearestSegment);
         case way:
-            return DeleteCommand.delete(editLayer, Collections.singleton(parameters.nearestSegment.way), false, silent);
+            return DeleteCommand.delete(Collections.singleton(parameters.nearestSegment.way), false, silent);
         case way_with_nodes:
-            return DeleteCommand.delete(editLayer, Collections.singleton(parameters.nearestSegment.way), true, silent);
+            return DeleteCommand.delete(Collections.singleton(parameters.nearestSegment.way), true, silent);
         case way_with_references:
-            return DeleteCommand.deleteWithReferences(editLayer, Collections.singleton(parameters.nearestSegment.way), true);
+            return DeleteCommand.deleteWithReferences(Collections.singleton(parameters.nearestSegment.way), true);
         default:
             return null;
         }
Index: src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(working copy)
@@ -487,7 +487,7 @@
                     nodes.remove(candidateNode);
                     newWay.setNodes(nodes);
                     if (nodes.size() < 2) {
-                        final Command deleteCmd = DeleteCommand.delete(getLayerManager().getEditLayer(), Collections.singleton(targetWay), true);
+                        final Command deleteCmd = DeleteCommand.delete(Collections.singleton(targetWay), true);
                         if (deleteCmd != null) {
                             MainApplication.undoRedo.add(deleteCmd);
                         }
@@ -499,7 +499,7 @@
                             tr("Cannot delete node that has tags"),
                             tr("Error"), JOptionPane.ERROR_MESSAGE);
                 } else {
-                    final Command deleteCmd = DeleteCommand.delete(getLayerManager().getEditLayer(), Collections.singleton(candidateNode), true);
+                    final Command deleteCmd = DeleteCommand.delete(Collections.singleton(candidateNode), true);
                     if (deleteCmd != null) {
                         MainApplication.undoRedo.add(deleteCmd);
                     }
Index: src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java	(working copy)
@@ -18,13 +18,13 @@
 import javax.swing.plaf.basic.BasicArrowButton;
 
 import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
Index: src/org/openstreetmap/josm/command/AddCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/AddCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/AddCommand.java	(working copy)
@@ -44,7 +44,9 @@
      * Creates the command and specify the element to add in the context of the given data layer.
      * @param layer The data layer. Must not be {@code null}
      * @param osm The primitive to add
+     * @deprecated to be removed end of 2017. Use {@link #AddCommand(DataSet, OsmPrimitive)} instead
      */
+    @Deprecated
     public AddCommand(OsmDataLayer layer, OsmPrimitive osm) {
         super(layer);
         this.osm = Objects.requireNonNull(osm, "osm");
Index: src/org/openstreetmap/josm/command/AddPrimitivesCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/AddPrimitivesCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/AddPrimitivesCommand.java	(working copy)
@@ -58,12 +58,26 @@
      * @param data The OSM primitives data to add. Must not be {@code null}
      * @param toSelect The OSM primitives to select at the end. Can be {@code null}
      * @param layer The target data layer. Must not be {@code null}
+     * @deprecated to be removed end of 2017. Use {@link #AddPrimitivesCommand(List, List, DataSet)} instead
      */
+    @Deprecated
     public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, OsmDataLayer layer) {
         super(layer);
         init(data, toSelect);
     }
 
+    /**
+     * Constructs a new {@code AddPrimitivesCommand} to add data to the given data set.
+     * @param data The OSM primitives data to add. Must not be {@code null}
+     * @param toSelect The OSM primitives to select at the end. Can be {@code null}
+     * @param ds The target data set. Must not be {@code null}
+     * @since xxx
+     */
+    public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, DataSet ds) {
+        super(ds);
+        init(data, toSelect);
+    }
+
     private void init(List<PrimitiveData> data, List<PrimitiveData> toSelect) {
         CheckParameterUtil.ensureParameterNotNull(data, "data");
         this.data = new ArrayList<>(data);
Index: src/org/openstreetmap/josm/command/ChangeCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/ChangeCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/ChangeCommand.java	(working copy)
@@ -44,7 +44,9 @@
      * @param layer The data layer
      * @param osm The existing primitive to modify
      * @param newOsm The new primitive
+     * @deprecated to be removed end of 2017. Use {@link #ChangeCommand(DataSet, OsmPrimitive, OsmPrimitive)} instead
      */
+    @Deprecated
     public ChangeCommand(OsmDataLayer layer, OsmPrimitive osm, OsmPrimitive newOsm) {
         super(layer);
         this.osm = osm;
Index: src/org/openstreetmap/josm/command/Command.java
===================================================================
--- src/org/openstreetmap/josm/command/Command.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/Command.java	(working copy)
@@ -34,7 +34,7 @@
  * Classes implementing Command modify a dataset in a specific way. A command is
  * one atomic action on a specific dataset, such as move or delete.
  *
- * The command remembers the {@link OsmDataLayer} it is operating on.
+ * The command remembers the {@link DataSet} it is operating on.
  *
  * @author imi
  * @since 21 (creation)
@@ -134,7 +134,11 @@
     /** the map of OsmPrimitives in the original state to OsmPrimitives in cloned state */
     private Map<OsmPrimitive, PrimitiveData> cloneMap = new HashMap<>();
 
-    /** the layer which this command is applied to */
+    /**
+     * the layer which this command is applied to
+     * @deprecated to be removed end of 2017. Use {@link #data} instead
+     */
+    @Deprecated
     private final OsmDataLayer layer;
 
     /** the dataset which this command is applied to */
@@ -145,7 +149,7 @@
      */
     public Command() {
         this.layer = MainApplication.getLayerManager().getEditLayer();
-        this.data = layer != null ? layer.data : null;
+        this.data = layer != null ? layer.data : Main.main.getEditDataSet();
     }
 
     /**
@@ -153,7 +157,9 @@
      *
      * @param layer the data layer. Must not be null.
      * @throws IllegalArgumentException if layer is null
+     * @deprecated to be removed end of 2017. Use {@link #Command(DataSet)} instead
      */
+    @Deprecated
     public Command(OsmDataLayer layer) {
         CheckParameterUtil.ensureParameterNotNull(layer, "layer");
         this.layer = layer;
@@ -215,12 +221,27 @@
      *
      * @param oldLayer the old layer that was removed
      * @return true if this command is invalid after that layer is removed.
+     * @deprecated to be removed end of 2017. Use {@link #invalidBecauseDatasetRemoved} instead
      */
+    @Deprecated
     public boolean invalidBecauselayerRemoved(Layer oldLayer) {
         return layer == oldLayer;
     }
 
     /**
+     * Called when a dataset has been removed to have the command remove itself from
+     * any buffer if it is not longer applicable to it (e.g. it was part of
+     * the removed dataset)
+     *
+     * @param oldDataset the old data set that was removed
+     * @return true if this command is invalid after that data set is removed.
+     * @since xxx
+     */
+    public boolean invalidBecauseDatasetRemoved(DataSet oldDataset) {
+        return data == oldDataset;
+    }
+
+    /**
      * Lets other commands access the original version
      * of the object. Usually for undoing.
      * @param osm The requested OSM object
@@ -233,7 +254,9 @@
     /**
      * Replies the layer this command is (or was) applied to.
      * @return the layer this command is (or was) applied to
+     * @deprecated to be removed end of 2017. Use {@link #getAffectedDataSet} instead
      */
+    @Deprecated
     protected OsmDataLayer getLayer() {
         return layer;
     }
@@ -370,7 +393,9 @@
     /**
      * Invalidate all layers that were affected by this command.
      * @see Layer#invalidate()
+     * @deprecated to be removed end of 2017
      */
+    @Deprecated
     public void invalidateAffectedLayers() {
         OsmDataLayer layer = getLayer();
         if (layer != null) {
Index: src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/DeleteCommand.java	(working copy)
@@ -107,27 +107,42 @@
     }
 
     /**
-     * Constructor for a single data item. Use the collection constructor to delete multiple
-     * objects.
+     * Constructor for a single data item. Use the collection constructor to delete multiple objects.
      *
      * @param layer the layer context for deleting this primitive. Must not be null.
      * @param data the primitive to delete. Must not be null.
      * @throws IllegalArgumentException if data is null
      * @throws IllegalArgumentException if layer is null
+     * @deprecated to be removed end of 2017. Use {@link #DeleteCommand(DataSet, OsmPrimitive)} instead
      */
+    @Deprecated
     public DeleteCommand(OsmDataLayer layer, OsmPrimitive data) {
         this(layer, Collections.singleton(data));
     }
 
     /**
-     * Constructor for a collection of data to be deleted in the context of
-     * a specific layer
+     * Constructor for a single data item. Use the collection constructor to delete multiple objects.
+     *
+     * @param dataset the data set context for deleting this primitive. Must not be null.
+     * @param data the primitive to delete. Must not be null.
+     * @throws IllegalArgumentException if data is null
+     * @throws IllegalArgumentException if layer is null
+     * @since xxx
+     */
+    public DeleteCommand(DataSet dataset, OsmPrimitive data) {
+        this(dataset, Collections.singleton(data));
+    }
+
+    /**
+     * Constructor for a collection of data to be deleted in the context of a specific layer
      *
      * @param layer the layer context for deleting these primitives. Must not be null.
      * @param data the primitives to delete. Must neither be null nor empty.
      * @throws IllegalArgumentException if layer is null
      * @throws IllegalArgumentException if data is null or empty
+     * @deprecated to be removed end of 2017. Use {@link #DeleteCommand(DataSet, Collection)} instead
      */
+    @Deprecated
     public DeleteCommand(OsmDataLayer layer, Collection<? extends OsmPrimitive> data) {
         super(layer);
         CheckParameterUtil.ensureParameterNotNull(data, "data");
@@ -136,8 +151,7 @@
     }
 
     /**
-     * Constructor for a collection of data to be deleted in the context of
-     * a specific data set
+     * Constructor for a collection of data to be deleted in the context of a specific data set
      *
      * @param dataset the dataset context for deleting these primitives. Must not be null.
      * @param data the primitives to delete. Must neither be null nor empty.
@@ -285,9 +299,27 @@
      * @param silent  Set to true if the user should not be bugged with additional dialogs
      * @return command A command to perform the deletions, or null of there is nothing to delete.
      * @throws IllegalArgumentException if layer is null
+     * @deprecated to be removed end of 2017. Use {@link #deleteWithReferences(Collection, boolean)} instead
      */
+    @Deprecated
     public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean silent) {
-        CheckParameterUtil.ensureParameterNotNull(layer, "layer");
+        return deleteWithReferences(selection, silent);
+    }
+
+    /**
+     * Delete the primitives and everything they reference.
+     *
+     * If a node is deleted, the node and all ways and relations the node is part of are deleted as well.
+     * If a way is deleted, all relations the way is member of are also deleted.
+     * If a way is deleted, only the way and no nodes are deleted.
+     *
+     * @param selection The list of all object to be deleted.
+     * @param silent  Set to true if the user should not be bugged with additional dialogs
+     * @return command A command to perform the deletions, or null of there is nothing to delete.
+     * @throws IllegalArgumentException if layer is null
+     * @since xxx
+     */
+    public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection, boolean silent) {
         if (selection == null || selection.isEmpty()) return null;
         Set<OsmPrimitive> parents = OsmPrimitive.getReferrer(selection);
         parents.addAll(selection);
@@ -296,7 +328,7 @@
             return null;
         if (!silent && !checkAndConfirmOutlyingDelete(parents, null))
             return null;
-        return new DeleteCommand(layer, parents);
+        return new DeleteCommand(parents.iterator().next().getDataSet(), parents);
     }
 
     /**
@@ -306,13 +338,31 @@
      * If a way is deleted, all relations the way is member of are also deleted.
      * If a way is deleted, only the way and no nodes are deleted.
      *
-     * @param layer the {@link OsmDataLayer} in whose context primitives are deleted. Must not be null.
+     * @param layer unused
      * @param selection The list of all object to be deleted.
      * @return command A command to perform the deletions, or null of there is nothing to delete.
      * @throws IllegalArgumentException if layer is null
+     * @deprecated to be removed end of 2017. Use {@link #deleteWithReferences(Collection)} instead
      */
+    @Deprecated
     public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
-        return deleteWithReferences(layer, selection, false);
+        return deleteWithReferences(selection);
+    }
+
+    /**
+     * Delete the primitives and everything they reference.
+     *
+     * If a node is deleted, the node and all ways and relations the node is part of are deleted as well.
+     * If a way is deleted, all relations the way is member of are also deleted.
+     * If a way is deleted, only the way and no nodes are deleted.
+     *
+     * @param selection The list of all object to be deleted.
+     * @return command A command to perform the deletions, or null of there is nothing to delete.
+     * @throws IllegalArgumentException if layer is null
+     * @since xxx
+     */
+    public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
+        return deleteWithReferences(selection, false);
     }
 
     /**
@@ -324,12 +374,31 @@
      * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
      * they are part of a relation, inform the user and do not delete.
      *
-     * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted
+     * @param layer unused
      * @param selection the objects to delete.
      * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @deprecated to be removed end of 2017. Use {@link #delete(Collection)} instead
      */
+    @Deprecated
     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
-        return delete(layer, selection, true, false);
+        return delete(selection);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     *
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     *
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     *
+     * @param selection the objects to delete.
+     * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @since xxx
+     */
+    public static Command delete(Collection<? extends OsmPrimitive> selection) {
+        return delete(selection, true, false);
     }
 
     /**
@@ -375,14 +444,34 @@
      * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
      * they are part of a relation, inform the user and do not delete.
      *
-     * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted
+     * @param layer unused
      * @param selection the objects to delete.
      * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
      * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @deprecated to be removed end of 2017. Use {@link #delete(Collection, boolean)} instead
      */
+    @Deprecated
     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection,
             boolean alsoDeleteNodesInWay) {
-        return delete(layer, selection, alsoDeleteNodesInWay, false /* not silent */);
+        return delete(selection, alsoDeleteNodesInWay);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     *
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     *
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     *
+     * @param selection the objects to delete.
+     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
+     * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @since xxx
+     */
+    public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
+        return delete(selection, alsoDeleteNodesInWay, false /* not silent */);
     }
 
     /**
@@ -394,14 +483,35 @@
      * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
      * they are part of a relation, inform the user and do not delete.
      *
-     * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted
+     * @param layer unused
      * @param selection the objects to delete.
      * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
      * @param silent set to true if the user should not be bugged with additional questions
      * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @deprecated to be removed end of 2017. Use {@link #delete(Collection, boolean, boolean)} instead
      */
+    @Deprecated
     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection,
             boolean alsoDeleteNodesInWay, boolean silent) {
+        return delete(selection, alsoDeleteNodesInWay, silent);
+    }
+
+    /**
+     * Try to delete all given primitives.
+     *
+     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
+     * relation, inform the user and do not delete.
+     *
+     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
+     * they are part of a relation, inform the user and do not delete.
+     *
+     * @param selection the objects to delete.
+     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
+     * @param silent set to true if the user should not be bugged with additional questions
+     * @return command a command to perform the deletions, or null if there is nothing to delete.
+     * @since xxx
+     */
+    public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay, boolean silent) {
         if (selection == null || selection.isEmpty())
             return null;
 
@@ -459,8 +569,7 @@
         // build the delete command
         //
         if (!primitivesToDelete.isEmpty()) {
-            cmds.add(layer != null ? new DeleteCommand(layer, primitivesToDelete) :
-                new DeleteCommand(primitivesToDelete.iterator().next().getDataSet(), primitivesToDelete));
+            cmds.add(new DeleteCommand(primitivesToDelete.iterator().next().getDataSet(), primitivesToDelete));
         }
 
         return new SequenceCommand(tr("Delete"), cmds);
@@ -468,13 +577,25 @@
 
     /**
      * Create a command that deletes a single way segment. The way may be split by this.
-     * @param layer The layer the segment is in.
+     * @param layer unused
      * @param ws The way segment that should be deleted
      * @return A matching command to safely delete that segment.
+     * @deprecated to be removed end of 2017. Use {@link #deleteWaySegment(WaySegment)} instead
      */
+    @Deprecated
     public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) {
+        return deleteWaySegment(ws);
+    }
+
+    /**
+     * Create a command that deletes a single way segment. The way may be split by this.
+     * @param ws The way segment that should be deleted
+     * @return A matching command to safely delete that segment.
+     * @since xxx
+     */
+    public static Command deleteWaySegment(WaySegment ws) {
         if (ws.way.getNodesCount() < 3)
-            return delete(layer, Collections.singleton(ws.way), false);
+            return delete(Collections.singleton(ws.way), false);
 
         if (ws.way.isClosed()) {
             // If the way is circular (first and last nodes are the same), the way shouldn't be splitted
@@ -505,7 +626,7 @@
             wnew.setNodes(n1);
             return new ChangeCommand(ws.way, wnew);
         } else {
-            SplitWayResult split = SplitWayAction.splitWay(layer, ws.way, Arrays.asList(n1, n2), Collections.<OsmPrimitive>emptyList());
+            SplitWayResult split = SplitWayAction.splitWay(ws.way, Arrays.asList(n1, n2), Collections.<OsmPrimitive>emptyList());
             return split != null ? split.getCommand() : null;
         }
     }
Index: src/org/openstreetmap/josm/command/PurgeCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/PurgeCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/PurgeCommand.java	(working copy)
@@ -53,7 +53,9 @@
      * @param layer OSM data layer
      * @param toPurge primitives to purge
      * @param makeIncomplete primitives to make incomplete
+     * @deprecated to be removed end of 2017. Use {@link #PurgeCommand(DataSet, Collection, Collection)} instead
      */
+    @Deprecated
     public PurgeCommand(OsmDataLayer layer, Collection<OsmPrimitive> toPurge, Collection<OsmPrimitive> makeIncomplete) {
         super(layer);
         init(toPurge, makeIncomplete);
@@ -318,8 +320,21 @@
      * @param toPurgeAdditionally optional list that will be filled with primitives to be purged that have not been in the selection
      * @return command to purge selected OSM primitives
      * @since 12688
+     * @deprecated to be removed end of 2017. Use {@link #build(Collection, List)} instead
      */
+    @Deprecated
     public static PurgeCommand build(OsmDataLayer layer, Collection<OsmPrimitive> sel, List<OsmPrimitive> toPurgeAdditionally) {
+        return build(sel, toPurgeAdditionally);
+    }
+
+    /**
+     * Creates a new {@code PurgeCommand} to purge selected OSM primitives.
+     * @param sel selected OSM primitives
+     * @param toPurgeAdditionally optional list that will be filled with primitives to be purged that have not been in the selection
+     * @return command to purge selected OSM primitives
+     * @since xxx
+     */
+    public static PurgeCommand build(Collection<OsmPrimitive> sel, List<OsmPrimitive> toPurgeAdditionally) {
         Set<OsmPrimitive> toPurge = new HashSet<>(sel);
         // finally, contains all objects that are purged
         Set<OsmPrimitive> toPurgeChecked = new HashSet<>();
@@ -422,8 +437,7 @@
             }
         }
 
-        return layer != null ? new PurgeCommand(layer, toPurgeChecked, makeIncomplete)
-                : new PurgeCommand(toPurgeChecked.iterator().next().getDataSet(), toPurgeChecked, makeIncomplete);
+        return new PurgeCommand(toPurgeChecked.iterator().next().getDataSet(), toPurgeChecked, makeIncomplete);
     }
 
     private static boolean hasOnlyIncompleteMembers(
Index: src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java	(working copy)
@@ -15,7 +15,6 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -32,7 +31,9 @@
      * Constructs a new {@code ConflictAddCommand}.
      * @param layer the data layer. Must not be null.
      * @param conflict the conflict to add
+     * @deprecated to be removed end of 2017. Use {@link #ConflictAddCommand(DataSet, Conflict)} instead
      */
+    @Deprecated
     public ConflictAddCommand(OsmDataLayer layer, Conflict<? extends OsmPrimitive> conflict) {
         super(layer);
         this.conflict = conflict;
@@ -55,7 +56,7 @@
                 tr("<html>Layer ''{0}'' already has a conflict for object<br>"
                         + "''{1}''.<br>"
                         + "This conflict cannot be added.</html>",
-                        Utils.escapeReservedCharactersHTML(getLayer().getName()),
+                        Utils.escapeReservedCharactersHTML(getAffectedDataSet().getName()),
                         Utils.escapeReservedCharactersHTML(conflict.getMy().getDisplayName(DefaultNameFormatter.getInstance()))
                 ),
                 tr("Double conflict"),
@@ -76,14 +77,15 @@
 
     @Override
     public void undoCommand() {
-        if (MainApplication.isDisplayingMapView() && !MainApplication.getLayerManager().containsLayer(getLayer())) {
+        DataSet ds = getAffectedDataSet();
+        if (!Main.main.containsDataSet(ds)) {
             Logging.warn(tr("Layer ''{0}'' does not exist any more. Cannot remove conflict for object ''{1}''.",
-                    getLayer().getName(),
+                    ds.getName(),
                     conflict.getMy().getDisplayName(DefaultNameFormatter.getInstance())
             ));
             return;
         }
-        getAffectedDataSet().getConflicts().remove(conflict);
+        ds.getConflicts().remove(conflict);
     }
 
     @Override
Index: src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java	(working copy)
@@ -5,11 +5,11 @@
 
 import java.util.Objects;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.conflict.ConflictCollection;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Logging;
 
@@ -23,23 +23,31 @@
  */
 public abstract class ConflictResolveCommand extends Command {
     /** the list of resolved conflicts */
-    private final ConflictCollection resolvedConflicts;
+    private final ConflictCollection resolvedConflicts = new ConflictCollection();
 
     /**
      * Constructs a new {@code ConflictResolveCommand} in the context of the current edit layer, if any.
      */
     public ConflictResolveCommand() {
-        super();
-        resolvedConflicts = new ConflictCollection();
+        // Do nothing
     }
 
     /**
      * Constructs a new {@code ConflictResolveCommand} in the context of a given data layer.
      * @param layer the data layer. Must not be null.
+     * @deprecated to be removed end of 2017. Use {@link #ConflictResolveCommand(DataSet)} instead
      */
+    @Deprecated
     public ConflictResolveCommand(OsmDataLayer layer) {
         super(layer);
-        resolvedConflicts = new ConflictCollection();
+    }
+
+    /**
+     * Constructs a new {@code ConflictResolveCommand} in the context of a given data set.
+     * @param ds the data set. Must not be null.
+     */
+    public ConflictResolveCommand(DataSet ds) {
+        super(ds);
     }
 
     /**
@@ -55,7 +63,7 @@
 
     /**
      * reconstitutes all remembered conflicts. Add the remembered conflicts to the
-     * set of conflicts of the {@link OsmDataLayer} this command was applied to.
+     * set of conflicts of the {@link DataSet} this command was applied to.
      *
      */
     protected void reconstituteConflicts() {
@@ -71,17 +79,16 @@
     public void undoCommand() {
         super.undoCommand();
 
-        if (MainApplication.isDisplayingMapView()) {
-            if (!MainApplication.getLayerManager().containsLayer(getLayer())) {
-                Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
-                        this.toString(),
-                        getLayer().toString()
-                ));
-                return;
-            }
-
-            MainApplication.getLayerManager().setActiveLayer(getLayer());
+        DataSet ds = getAffectedDataSet();
+        if (!Main.main.containsDataSet(ds)) {
+            Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
+                    this.toString(),
+                    ds.getName()
+            ));
+            return;
         }
+
+        Main.main.setEditDataSet(ds);
         reconstituteConflicts();
     }
 
Index: src/org/openstreetmap/josm/command/conflict/RelationMemberConflictResolverCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/conflict/RelationMemberConflictResolverCommand.java	(revision 12702)
+++ src/org/openstreetmap/josm/command/conflict/RelationMemberConflictResolverCommand.java	(working copy)
@@ -9,13 +9,12 @@
 
 import javax.swing.Icon;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
 
@@ -71,17 +70,16 @@
 
     @Override
     public void undoCommand() {
-        OsmDataLayer layer = getLayer();
-        if (!MainApplication.getLayerManager().containsLayer(layer)) {
+        DataSet editDs = getAffectedDataSet();
+        if (!Main.main.containsDataSet(editDs)) {
             Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
                     this.toString(),
-                    layer.toString()
+                    editDs.getName()
             ));
             return;
         }
 
-        MainApplication.getLayerManager().setActiveLayer(layer);
-        DataSet editDs = MainApplication.getLayerManager().getEditDataSet();
+        Main.main.setEditDataSet(editDs);
 
         // restore the former state
         //
Index: src/org/openstreetmap/josm/data/UndoRedoHandler.java
===================================================================
--- src/org/openstreetmap/josm/data/UndoRedoHandler.java	(revision 12702)
+++ src/org/openstreetmap/josm/data/UndoRedoHandler.java	(working copy)
@@ -10,22 +10,14 @@
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
-import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
 /**
- * This is the global undo/redo handler for all {@link OsmDataLayer}s.
+ * This is the global undo/redo handler for all {@link DataSet}s.
  * <p>
- * If you want to change a data layer, you can use {@link #add(Command)} to execute a command on it and make that command undoable.
+ * If you want to change a data set, you can use {@link #add(Command)} to execute a command on it and make that command undoable.
  */
-public class UndoRedoHandler implements LayerChangeListener {
+public class UndoRedoHandler {
 
     /**
      * All commands that were made on the dataset. Don't write from outside!
@@ -44,7 +36,21 @@
      * Constructs a new {@code UndoRedoHandler}.
      */
     public UndoRedoHandler() {
-        MainApplication.getLayerManager().addLayerChangeListener(this);
+        // Do nothing
+    }
+
+    /**
+     * A listener that gets notified of command queue (undo/redo) size changes.
+     * @since xxx (moved from {@code OsmDataLayer}
+     */
+    @FunctionalInterface
+    public interface CommandQueueListener {
+        /**
+         * Notifies the listener about the new queue size
+         * @param queueSize Undo stack size
+         * @param redoSize Redo stack size
+         */
+        void commandChanged(int queueSize, int redoSize);
     }
 
     /**
@@ -196,21 +202,22 @@
     }
 
     /**
-     * Resets all commands that affect the given layer.
-     * @param layer The layer that was affected.
+     * Resets all commands that affect the given dataset.
+     * @param dataSet The data set that was affected.
+     * @since xxx
      */
-    public void clean(Layer layer) {
-        if (layer == null)
+    public void clean(DataSet dataSet) {
+        if (dataSet == null)
             return;
         boolean changed = false;
         for (Iterator<Command> it = commands.iterator(); it.hasNext();) {
-            if (it.next().invalidBecauselayerRemoved(layer)) {
+            if (it.next().invalidBecauseDatasetRemoved(dataSet)) {
                 it.remove();
                 changed = true;
             }
         }
         for (Iterator<Command> it = redoCommands.iterator(); it.hasNext();) {
-            if (it.next().invalidBecauselayerRemoved(layer)) {
+            if (it.next().invalidBecauseDatasetRemoved(dataSet)) {
                 it.remove();
                 changed = true;
             }
@@ -220,21 +227,6 @@
         }
     }
 
-    @Override
-    public void layerRemoving(LayerRemoveEvent e) {
-        clean(e.getRemovedLayer());
-    }
-
-    @Override
-    public void layerAdded(LayerAddEvent e) {
-        // Do nothing
-    }
-
-    @Override
-    public void layerOrderChanged(LayerOrderChangeEvent e) {
-        // Do nothing
-    }
-
     /**
      * Removes a command queue listener.
      * @param l The command queue listener to remove
Index: src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 12702)
+++ src/org/openstreetmap/josm/data/osm/DataSet.java	(working copy)
@@ -168,6 +168,7 @@
     // Events that occurred while dataset was locked but should be fired after write lock is released
     private final List<AbstractDatasetChangedEvent> cachedEvents = new ArrayList<>();
 
+    private String name;
     private UploadPolicy uploadPolicy;
 
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
@@ -1359,6 +1360,24 @@
         return conflicts;
     }
 
+    /**
+     * Returns the name of this data set (optional).
+     * @return the name of this data set. Can be {@code null}
+     * @since xxx
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of this data set.
+     * @param name the new name of this data set. Can be {@code null} to reset it
+     * @since xxx
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
     /* --------------------------------------------------------------------------------- */
     /* interface ProjectionChangeListner                                                 */
     /* --------------------------------------------------------------------------------- */
Index: src/org/openstreetmap/josm/data/validation/Test.java
===================================================================
--- src/org/openstreetmap/josm/data/validation/Test.java	(revision 12702)
+++ src/org/openstreetmap/josm/data/validation/Test.java	(working copy)
@@ -22,7 +22,6 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.search.SearchCompiler.NotOutsideDataSourceArea;
 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.tools.GBC;
@@ -330,7 +329,7 @@
             }
         }
         if (!primitivesToDelete.isEmpty()) {
-            return DeleteCommand.delete(MainApplication.getLayerManager().getEditLayer(), primitivesToDelete);
+            return DeleteCommand.delete(primitivesToDelete);
         } else {
             return null;
         }
Index: src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplication.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/MainApplication.java	(working copy)
@@ -71,6 +71,7 @@
 import org.openstreetmap.josm.actions.search.SearchAction;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.UndoRedoHandler;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -83,8 +84,13 @@
 import org.openstreetmap.josm.gui.io.CustomConfigurator.XMLCommandProcessor;
 import org.openstreetmap.josm.gui.io.SaveLayersDialog;
 import org.openstreetmap.josm.gui.layer.AutosaveTask;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
 import org.openstreetmap.josm.gui.layer.MainLayerManager;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.TMSLayer;
 import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
 import org.openstreetmap.josm.gui.preferences.display.LafPreference;
@@ -186,9 +192,9 @@
 
     /**
      * The commands undo/redo handler.
-     * @since 12641 (as a replacement to {@code Main.main.undoRedo})
+     * @since 12641
      */
-    public static final UndoRedoHandler undoRedo = new UndoRedoHandler(); // Must be declared after layerManager
+    public static UndoRedoHandler undoRedo;
 
     /**
      * Listener that sets the enabled state of undo/redo menu entries.
@@ -212,6 +218,26 @@
      */
     public MainApplication(MainFrame mainFrame) {
         this.mainFrame = mainFrame;
+        undoRedo = super.undoRedo;
+        getLayerManager().addLayerChangeListener(new LayerChangeListener() {
+            @Override
+            public void layerRemoving(LayerRemoveEvent e) {
+                Layer layer = e.getRemovedLayer();
+                if (layer instanceof OsmDataLayer) {
+                    undoRedo.clean(((OsmDataLayer) layer).data);
+                }
+            }
+
+            @Override
+            public void layerOrderChanged(LayerOrderChangeEvent e) {
+                // Do nothing
+            }
+
+            @Override
+            public void layerAdded(LayerAddEvent e) {
+                // Do nothing
+            }
+        });
     }
 
     /**
@@ -406,6 +432,20 @@
         return getLayerManager().getEditDataSet();
     }
 
+    @Override
+    public void setEditDataSet(DataSet ds) {
+        Optional<OsmDataLayer> layer = getLayerManager().getLayersOfType(OsmDataLayer.class).stream()
+                .filter(l -> l.data.equals(ds)).findFirst();
+        if (layer.isPresent()) {
+            getLayerManager().setActiveLayer(layer.get());
+        }
+    }
+
+    @Override
+    public boolean containsDataSet(DataSet ds) {
+        return getLayerManager().getLayersOfType(OsmDataLayer.class).stream().anyMatch(l -> l.data.equals(ds));
+    }
+
     /**
      * Returns the command-line arguments used to run the application.
      * @return the command-line arguments used to run the application
Index: src/org/openstreetmap/josm/gui/datatransfer/importers/PrimitiveDataPaster.java
===================================================================
--- src/org/openstreetmap/josm/gui/datatransfer/importers/PrimitiveDataPaster.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/datatransfer/importers/PrimitiveDataPaster.java	(working copy)
@@ -82,7 +82,7 @@
                 throw BugReport.intercept(e).put("data", data);
             }
         }
-        return new AddPrimitivesCommand(bufferCopy, toSelect, layer);
+        return new AddPrimitivesCommand(bufferCopy, toSelect, layer.data);
     }
 
     private static EnumMap<OsmPrimitiveType, Map<Long, Long>> generateNewPrimitives(PrimitiveTransferData pasteBuffer,
Index: src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/dialogs/CommandStackDialog.java	(working copy)
@@ -38,12 +38,12 @@
 import org.openstreetmap.josm.actions.AutoScaleAction;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.PseudoCommand;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
Index: src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(working copy)
@@ -10,6 +10,7 @@
 import javax.swing.JOptionPane;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
@@ -18,7 +19,6 @@
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
 import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
Index: src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java	(working copy)
@@ -72,7 +72,7 @@
         // tags, don't add an empty relation
         if (newRelation.getMembersCount() == 0 && !newRelation.hasKeys())
             return;
-        MainApplication.undoRedo.add(new AddCommand(layer, newRelation));
+        MainApplication.undoRedo.add(new AddCommand(layer.data, newRelation));
 
         // make sure everybody is notified about the changes
         //
@@ -94,7 +94,7 @@
         tagEditorModel.applyToPrimitive(editedRelation);
         memberTableModel.applyToRelation(editedRelation);
         Conflict<Relation> conflict = new Conflict<>(editor.getRelation(), editedRelation);
-        MainApplication.undoRedo.add(new ConflictAddCommand(layer, conflict));
+        MainApplication.undoRedo.add(new ConflictAddCommand(layer.data, conflict));
     }
 
     /**
Index: src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/layer/Layer.java	(working copy)
@@ -338,7 +338,7 @@
      *
      * @param name the name. If null, the name is set to the empty string.
      */
-    public final void setName(String name) {
+    public void setName(String name) {
         if (this.name != null) {
             removeColorPropertyListener();
         }
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 12702)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(working copy)
@@ -294,19 +294,6 @@
     }
 
     /**
-     * A listener that gets notified of command queue (undo/redo) size changes.
-     */
-    @FunctionalInterface
-    public interface CommandQueueListener {
-        /**
-         * Notifies the listener about the new queue size
-         * @param queueSize Undo stack size
-         * @param redoSize Redo stack size
-         */
-        void commandChanged(int queueSize, int redoSize);
-    }
-
-    /**
      * Listener called when a state of this layer has changed.
      * @since 10600 (functional interface)
      */
@@ -400,6 +387,7 @@
         super(name);
         CheckParameterUtil.ensureParameterNotNull(data, "data");
         this.data = data;
+        this.data.setName(name);
         this.setAssociatedFile(associatedFile);
         data.addDataSetListener(new DataSetListenerAdapter(this));
         data.addDataSetListener(MultipolygonCache.getInstance());
@@ -602,7 +590,7 @@
         if (processed == null || processed.isEmpty())
             return;
 
-        MainApplication.undoRedo.clean(this);
+        MainApplication.undoRedo.clean(data);
 
         // if uploaded, clean the modified flags as well
         data.cleanupDeletedPrimitives();
@@ -1145,4 +1133,12 @@
     public void highlightUpdated(HighlightUpdateEvent e) {
         invalidate();
     }
+
+    @Override
+    public void setName(String name) {
+        if (data != null) {
+            data.setName(name);
+        }
+        super.setName(name);
+    }
 }
Index: src/org/openstreetmap/josm/tools/Geometry.java
===================================================================
--- src/org/openstreetmap/josm/tools/Geometry.java	(revision 12702)
+++ src/org/openstreetmap/josm/tools/Geometry.java	(working copy)
@@ -36,7 +36,6 @@
 import org.openstreetmap.josm.data.projection.Projections;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
  * Some tools for geometry related tasks.
@@ -102,7 +101,6 @@
             changedWays[pos] = false;
         }
 
-        OsmDataLayer layer = MainApplication.getLayerManager().getEditLayer();
         DataSet dataset = ways.get(0).getDataSet();
 
         //iterate over all way pairs and introduce the intersections
@@ -209,7 +207,7 @@
                                 intersectionNodes.add(intNode);
 
                                 if (intNode == newNode) {
-                                    cmds.add(layer != null ? new AddCommand(layer, intNode) : new AddCommand(dataset, intNode));
+                                    cmds.add(new AddCommand(dataset, intNode));
                                 }
                             }
                         } else if (test && !intersectionNodes.isEmpty())
Index: src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java
===================================================================
--- src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java	(revision 12702)
+++ src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java	(working copy)
@@ -103,7 +103,7 @@
             w.removeAll();
         }
         // Purge all other ways and relations so dataset only contains lefthand traffic data
-        PurgeCommand.build(null, toPurge, null).executeCommand();
+        PurgeCommand.build(toPurge, null).executeCommand();
         // Combine adjacent countries into a single polygon
         Collection<Way> optimizedWays = new ArrayList<>();
         List<Multipolygon> areas = JoinAreasAction.collectMultipolygons(ways);
Index: test/unit/org/openstreetmap/josm/command/CommandTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/command/CommandTest.java	(revision 12702)
+++ test/unit/org/openstreetmap/josm/command/CommandTest.java	(working copy)
@@ -49,29 +49,31 @@
     }
 
     /**
-     * Test {@link Command#invalidBecauselayerRemoved(org.openstreetmap.josm.gui.layer.Layer)}
+     * Test {@link Command#invalidBecauseDatasetRemoved}
      */
     @Test
-    public void testInvalidBecauselayerRemoved() {
+    public void testInvalidBecauseDatasetRemoved() {
         OsmDataLayer layer2 = new OsmDataLayer(new DataSet(), "test", null);
 
         Command command = new NopCommand();
-        assertFalse(command.invalidBecauselayerRemoved(layer2));
-        assertTrue(command.invalidBecauselayerRemoved(testData.layer));
+        assertFalse(command.invalidBecauseDatasetRemoved(layer2.data));
+        assertTrue(command.invalidBecauseDatasetRemoved(testData.layer.data));
 
-        Command command2 = new NopCommand(layer2);
-        assertTrue(command2.invalidBecauselayerRemoved(layer2));
-        assertFalse(command2.invalidBecauselayerRemoved(testData.layer));
+        Command command2 = new NopCommand(layer2.data);
+        assertTrue(command2.invalidBecauseDatasetRemoved(layer2.data));
+        assertFalse(command2.invalidBecauseDatasetRemoved(testData.layer.data));
     }
 
     /**
      * Test {@link Command#getLayer()}
+     * @deprecated to be removed end of 2017
      */
     @Test
+    @Deprecated
     public void testGetLayer() {
         OsmDataLayer layer2 = new OsmDataLayer(new DataSet(), "test", null);
         Command command = new NopCommand();
-        Command command2 = new NopCommand(layer2);
+        Command command2 = new NopCommand(layer2.data);
         assertSame(testData.layer, command.getLayer());
         assertSame(layer2, command2.getLayer());
     }
@@ -97,8 +99,8 @@
             super();
         }
 
-        NopCommand(OsmDataLayer layer) {
-            super(layer);
+        NopCommand(DataSet dataset) {
+            super(dataset);
         }
 
         @Override
