Index: trunk/src/org/openstreetmap/josm/command/ChangeNodesCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/ChangeNodesCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/ChangeNodesCommand.java	(revision 10663)
@@ -38,4 +38,7 @@
         this.way = way;
         this.newNodes = newNodes;
+        if (newNodes.isEmpty()) {
+            throw new IllegalArgumentException("Cannot set nodes to be an empty list.");
+        }
     }
 
@@ -55,5 +58,5 @@
     @Override
     public String getDescriptionText() {
-        return tr("Changed nodes of {0}", way.getDisplayName(DefaultNameFormatter.getInstance()));
+        return tr("Change nodes of {0}", way.getDisplayName(DefaultNameFormatter.getInstance()));
     }
 
Index: trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java	(revision 10663)
@@ -156,5 +156,5 @@
             String msg;
             Map.Entry<String, String> entry = tags.entrySet().iterator().next();
-            if (entry.getValue() == null) {
+            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                 switch(OsmPrimitiveType.from(primitive)) {
                 case NODE: msg = marktr("Remove \"{0}\" for node ''{1}''"); break;
@@ -175,5 +175,5 @@
         } else if (objects.size() > 1 && tags.size() == 1) {
             Map.Entry<String, String> entry = tags.entrySet().iterator().next();
-            if (entry.getValue() == null) {
+            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                 /* I18n: plural form for objects, but value < 2 not possible! */
                 text = trn("Remove \"{0}\" for {1} object", "Remove \"{0}\" for {1} objects", objects.size(), entry.getKey(), objects.size());
@@ -186,5 +186,5 @@
             boolean allnull = true;
             for (Map.Entry<String, String> tag : this.tags.entrySet()) {
-                if (tag.getValue() != null) {
+                if (tag.getValue() != null && !tag.getValue().isEmpty()) {
                     allnull = false;
                     break;
@@ -226,5 +226,4 @@
                     return Collections.singleton(osm);
                 }
-
             });
         }
Index: trunk/src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java	(revision 10663)
@@ -66,5 +66,5 @@
             return false; // save old
         for (OsmPrimitive osm : objects) {
-            if (osm.hasKeys()) {
+            if (osm.hasKey(key) || osm.hasKey(newKey)) {
                 osm.setModified(true);
                 String oldValue = osm.get(key);
@@ -87,7 +87,7 @@
             NameVisitor v = new NameVisitor();
             objects.get(0).accept(v);
-            text += ' '+tr(v.className)+' '+v.name;
+            text += " "+tr(v.className)+" "+v.name;
         } else {
-            text += ' '+objects.size()+' '+trn("object", "objects", objects.size());
+            text += " "+objects.size()+" "+trn("object", "objects", objects.size());
         }
         return text;
@@ -108,13 +108,15 @@
         for (final OsmPrimitive osm : objects) {
             osm.accept(v);
+            final String name = v.name;
+            final Icon icon = v.icon;
             children.add(new PseudoCommand() {
                 @Override
                 public String getDescriptionText() {
-                    return v.name;
+                    return name;
                 }
 
                 @Override
                 public Icon getDescriptionIcon() {
-                    return v.icon;
+                    return icon;
                 }
 
Index: trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java	(revision 10663)
@@ -49,5 +49,5 @@
     public boolean executeCommand() {
         if (position < 0 || position >= relation.getMembersCount())
-            return false;
+            return true;
 
         oldRole = relation.getMember(position).getRole();
@@ -62,7 +62,9 @@
     @Override
     public void undoCommand() {
-        relation.setMember(position, new RelationMember(oldRole, relation.getMember(position).getMember()));
-        if (oldModified != null) {
-            relation.setModified(oldModified);
+        if (position >= 0 && position < relation.getMembersCount()) {
+            relation.setMember(position, new RelationMember(oldRole, relation.getMember(position).getMember()));
+            if (oldModified != null) {
+                relation.setModified(oldModified);
+            }
         }
     }
Index: trunk/src/org/openstreetmap/josm/command/Command.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/Command.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/Command.java	(revision 10663)
@@ -188,10 +188,8 @@
      * the removed layer)
      *
-     * @param oldLayer the old layer
-     * @return true if this command
+     * @param oldLayer the old layer that was removed
+     * @return true if this command is invalid after that layer is removed.
      */
     public boolean invalidBecauselayerRemoved(Layer oldLayer) {
-        if (!(oldLayer instanceof OsmDataLayer))
-            return false;
         return layer == oldLayer;
     }
Index: trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 10663)
@@ -51,4 +51,32 @@
  */
 public class DeleteCommand extends Command {
+    private static final class DeleteChildCommand implements PseudoCommand {
+        private final OsmPrimitive osm;
+
+        private DeleteChildCommand(OsmPrimitive osm) {
+            this.osm = osm;
+        }
+
+        @Override
+        public String getDescriptionText() {
+            return tr("Deleted ''{0}''", osm.getDisplayName(DefaultNameFormatter.getInstance()));
+        }
+
+        @Override
+        public Icon getDescriptionIcon() {
+            return ImageProvider.get(osm.getDisplayType());
+        }
+
+        @Override
+        public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
+            return Collections.singleton(osm);
+        }
+
+        @Override
+        public String toString() {
+            return "DeleteChildCommand [osm=" + osm + "]";
+        }
+    }
+
     /**
      * The primitives that get deleted.
@@ -65,6 +93,4 @@
     public DeleteCommand(Collection<? extends OsmPrimitive> data) {
         CheckParameterUtil.ensureParameterNotNull(data, "data");
-        if (data.isEmpty())
-            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
         this.toDelete = data;
         checkConsistency();
@@ -106,6 +132,4 @@
         super(layer);
         CheckParameterUtil.ensureParameterNotNull(data, "data");
-        if (data.isEmpty())
-            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
         this.toDelete = data;
         checkConsistency();
@@ -113,4 +137,7 @@
 
     private void checkConsistency() {
+        if (toDelete.isEmpty()) {
+            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
+        }
         for (OsmPrimitive p : toDelete) {
             if (p == null) {
@@ -216,19 +243,5 @@
             List<PseudoCommand> children = new ArrayList<>(toDelete.size());
             for (final OsmPrimitive osm : toDelete) {
-                children.add(new PseudoCommand() {
-
-                    @Override public String getDescriptionText() {
-                        return tr("Deleted ''{0}''", osm.getDisplayName(DefaultNameFormatter.getInstance()));
-                    }
-
-                    @Override public Icon getDescriptionIcon() {
-                        return ImageProvider.get(osm.getDisplayType());
-                    }
-
-                    @Override public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
-                        return Collections.singleton(osm);
-                    }
-
-                });
+                children.add(new DeleteChildCommand(osm));
             }
             return children;
@@ -441,4 +454,10 @@
     }
 
+    /**
+     * 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 ws The way segment that should be deleted
+     * @return A matching command to safely delete that segment.
+     */
     public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) {
         if (ws.way.getNodesCount() < 3)
Index: trunk/src/org/openstreetmap/josm/command/MoveCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/MoveCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/MoveCommand.java	(revision 10663)
@@ -243,4 +243,12 @@
     public Collection<Node> getParticipatingPrimitives() {
         return nodes;
+    }
+
+    /**
+     * Gets the offset.
+     * @return The current offset.
+     */
+    protected EastNorth getOffset() {
+        return new EastNorth(x, y);
     }
 
Index: trunk/src/org/openstreetmap/josm/command/RotateCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/RotateCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/RotateCommand.java	(revision 10663)
@@ -39,5 +39,5 @@
      * @param currentEN cuurent eats/north
      */
-    public RotateCommand(Collection<OsmPrimitive> objects, EastNorth currentEN) {
+    public RotateCommand(Collection<? extends OsmPrimitive> objects, EastNorth currentEN) {
         super(objects);
 
@@ -71,11 +71,19 @@
 
     /**
+     * Set the rotation angle.
+     * @param rotationAngle The rotate angle
+     */
+    protected void setRotationAngle(double rotationAngle) {
+        this.rotationAngle = rotationAngle;
+    }
+
+    /**
      * Rotate nodes.
      */
     @Override
     protected void transformNodes() {
+        double cosPhi = Math.cos(rotationAngle);
+        double sinPhi = Math.sin(rotationAngle);
         for (Node n : nodes) {
-            double cosPhi = Math.cos(rotationAngle);
-            double sinPhi = Math.sin(rotationAngle);
             EastNorth oldEastNorth = oldStates.get(n).getEastNorth();
             double x = oldEastNorth.east() - pivot.east();
Index: trunk/src/org/openstreetmap/josm/command/ScaleCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/ScaleCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/ScaleCommand.java	(revision 10663)
@@ -35,5 +35,5 @@
      * @param currentEN cuurent eats/north
      */
-    public ScaleCommand(Collection<OsmPrimitive> objects, EastNorth currentEN) {
+    public ScaleCommand(Collection<? extends OsmPrimitive> objects, EastNorth currentEN) {
         super(objects);
 
@@ -58,6 +58,14 @@
         double startDistance = pivot.distance(startEN);
         double currentDistance = pivot.distance(currentEN);
-        scalingFactor = Math.cos(startAngle-endAngle) * currentDistance / startDistance;
+        setScalingFactor(Math.cos(startAngle-endAngle) * currentDistance / startDistance);
         transformNodes();
+    }
+
+    /**
+     * Set the scaling factor
+     * @param scalingFactor The scaling factor.
+     */
+    protected void setScalingFactor(double scalingFactor) {
+        this.scalingFactor = scalingFactor;
     }
 
Index: trunk/src/org/openstreetmap/josm/command/SelectCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/SelectCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/SelectCommand.java	(revision 10663)
@@ -5,4 +5,6 @@
 
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Objects;
 
@@ -28,5 +30,9 @@
      */
     public SelectCommand(Collection<OsmPrimitive> newSelection) {
-        this.newSelection = newSelection;
+        if (newSelection == null || newSelection.isEmpty()) {
+            this.newSelection = Collections.emptySet();
+        } else {
+            this.newSelection = new HashSet<>(newSelection);
+        }
     }
 
Index: trunk/src/org/openstreetmap/josm/command/TransformNodesCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/TransformNodesCommand.java	(revision 10662)
+++ trunk/src/org/openstreetmap/josm/command/TransformNodesCommand.java	(revision 10663)
@@ -49,5 +49,5 @@
      * @param objects objects to fetch nodes from
      */
-    public TransformNodesCommand(Collection<OsmPrimitive> objects) {
+    public TransformNodesCommand(Collection<? extends OsmPrimitive> objects) {
         this.nodes = AllNodesVisitor.getAllNodes(objects);
         storeOldState();
