Index: /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 11060)
+++ /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 11061)
@@ -5,4 +5,5 @@
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
@@ -10,4 +11,5 @@
 import java.util.Locale;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -16,4 +18,5 @@
 import org.openstreetmap.josm.data.correction.RoleCorrection;
 import org.openstreetmap.josm.data.correction.TagCorrection;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmUtils;
@@ -64,5 +67,53 @@
     }
 
-    private static class StringSwitcher {
+    private interface IStringSwitcher extends Function<String, String> {
+
+        static IStringSwitcher combined(IStringSwitcher... switchers) {
+            return key -> {
+                for (IStringSwitcher switcher : switchers) {
+                    final String newKey = switcher.apply(key);
+                    if (!key.equals(newKey)) {
+                        return newKey;
+                    }
+                }
+                return key;
+            };
+        }
+
+        static IStringSwitcher compassCardinal() {
+            final List<String> cardinal = Arrays.asList(
+                    "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
+                    "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW");
+            return key -> {
+                final int index = cardinal.indexOf(key);
+                if (index >= 0) {
+                    return cardinal.get((index + cardinal.size() / 2) % cardinal.size());
+                }
+                return key;
+            };
+        }
+
+        static IStringSwitcher compassDegrees() {
+            return key -> {
+                if (!key.matches("\\d+")) {
+                    return key;
+                }
+                final int i = Integer.parseInt(key);
+                if (i < 0 || i > 360) {
+                    return key;
+                }
+                return Integer.toString((i + 180) % 360);
+            };
+        }
+
+        static IStringSwitcher compass() {
+            return combined(
+                    IStringSwitcher.compassCardinal(),
+                    IStringSwitcher.compassDegrees()
+            );
+        }
+    }
+
+    private static class StringSwitcher implements IStringSwitcher {
 
         private final String a;
@@ -76,4 +127,5 @@
         }
 
+        @Override
         public String apply(String text) {
             Matcher m = pattern.matcher(text);
@@ -128,15 +180,14 @@
                     newValue = OsmUtils.reverseval;
                 }
-                for (StringSwitcher prefixSuffixSwitcher : stringSwitchers) {
-                    newKey = prefixSuffixSwitcher.apply(key);
-                    if (!key.equals(newKey)) {
-                        break;
-                    }
-                }
-            } else if (key.startsWith("incline") || key.endsWith("incline")
-                    || key.startsWith("direction") || key.endsWith("direction")) {
+                newKey = COMBINED_SWITCHERS.apply(key);
+            } else if (key.startsWith("incline") || key.endsWith("incline")) {
                 newValue = UP_DOWN.apply(value);
                 if (newValue.equals(value)) {
                     newValue = invertNumber(value);
+                }
+            } else if (key.startsWith("direction") || key.endsWith("direction")) {
+                newValue = COMBINED_SWITCHERS.apply(value);
+                if (newValue.equals(value)) {
+                    newValue = IStringSwitcher.compass().apply(value);
                 }
             } else if (key.endsWith(":forward") || key.endsWith(":backward")) {
@@ -144,14 +195,6 @@
                 newKey = FORWARD_BACKWARD.apply(key);
             } else if (!ignoreKeyForCorrection(key)) {
-                for (StringSwitcher prefixSuffixSwitcher : stringSwitchers) {
-                    newKey = prefixSuffixSwitcher.apply(key);
-                    if (!key.equals(newKey)) {
-                        break;
-                    }
-                    newValue = prefixSuffixSwitcher.apply(value);
-                    if (!value.equals(newValue)) {
-                        break;
-                    }
-                }
+                newKey = COMBINED_SWITCHERS.apply(key);
+                newValue = COMBINED_SWITCHERS.apply(value);
             }
             return new Tag(newKey, newValue);
@@ -161,6 +204,5 @@
     private static final StringSwitcher FORWARD_BACKWARD = new StringSwitcher("forward", "backward");
     private static final StringSwitcher UP_DOWN = new StringSwitcher("up", "down");
-
-    private static final StringSwitcher[] stringSwitchers = new StringSwitcher[] {
+    private static final IStringSwitcher COMBINED_SWITCHERS = IStringSwitcher.combined(
         new StringSwitcher("left", "right"),
         new StringSwitcher("forwards", "backwards"),
@@ -168,5 +210,5 @@
         new StringSwitcher("north", "south"),
         FORWARD_BACKWARD, UP_DOWN
-    };
+    );
 
     /**
@@ -207,6 +249,7 @@
     static List<TagCorrection> getTagCorrections(Tagged way) {
         List<TagCorrection> tagCorrections = new ArrayList<>();
-        for (String key : way.keySet()) {
-            String value = way.get(key);
+        for (Map.Entry<String, String> entry : way.getKeys().entrySet()) {
+            final String key = entry.getKey();
+            final String value = entry.getValue();
             Tag newTag = TagSwitcher.apply(key, value);
             String newKey = newTag.getKey();
@@ -245,15 +288,6 @@
                 }
 
-                boolean found = false;
-                String newRole = null;
-                for (StringSwitcher prefixSuffixSwitcher : stringSwitchers) {
-                    newRole = prefixSuffixSwitcher.apply(member.getRole());
-                    if (!newRole.equals(member.getRole())) {
-                        found = true;
-                        break;
-                    }
-                }
-
-                if (found) {
+                final String newRole = COMBINED_SWITCHERS.apply(member.getRole());
+                if (!member.getRole().equals(newRole)) {
                     roleCorrections.add(new RoleCorrection(relation, position, member, newRole));
                 }
@@ -263,13 +297,24 @@
         }
         return roleCorrections;
+    }
+
+    static Map<OsmPrimitive, List<TagCorrection>> getTagCorrectionsMap(Way way) {
+        Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap = new HashMap<>();
+        List<TagCorrection> tagCorrections = getTagCorrections((Tagged) way);
+        if (!tagCorrections.isEmpty()) {
+            tagCorrectionsMap.put(way, tagCorrections);
+        }
+        for (Node node : way.getNodes()) {
+            final List<TagCorrection> corrections = getTagCorrections(node);
+            if (!corrections.isEmpty()) {
+                tagCorrectionsMap.put(node, corrections);
+            }
+        }
+        return tagCorrectionsMap;
     }
 
     @Override
     public Collection<Command> execute(Way oldway, Way way) throws UserCancelException {
-        Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap = new HashMap<>();
-        List<TagCorrection> tagCorrections = getTagCorrections(way);
-        if (!tagCorrections.isEmpty()) {
-            tagCorrectionsMap.put(way, tagCorrections);
-        }
+        Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap = getTagCorrectionsMap(way);
 
         Map<OsmPrimitive, List<RoleCorrection>> roleCorrectionMap = new HashMap<>();
Index: /trunk/src/org/openstreetmap/josm/data/correction/TagCorrection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/correction/TagCorrection.java	(revision 11060)
+++ /trunk/src/org/openstreetmap/josm/data/correction/TagCorrection.java	(revision 11061)
@@ -1,4 +1,6 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.correction;
+
+import java.util.Objects;
 
 /**
@@ -47,3 +49,19 @@
         return !newValue.equals(oldValue);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof TagCorrection)) return false;
+        TagCorrection that = (TagCorrection) o;
+        return Objects.equals(oldKey, that.oldKey) &&
+                Objects.equals(newKey, that.newKey) &&
+                Objects.equals(oldValue, that.oldValue) &&
+                Objects.equals(newValue, that.newValue);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(oldKey, newKey, oldValue, newValue);
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/corrector/ReverseWayTagCorrectorTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/corrector/ReverseWayTagCorrectorTest.java	(revision 11060)
+++ /trunk/test/unit/org/openstreetmap/josm/corrector/ReverseWayTagCorrectorTest.java	(revision 11061)
@@ -1,9 +1,19 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.corrector;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
+import org.openstreetmap.josm.data.correction.TagCorrection;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmUtils;
 import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
 
@@ -39,4 +49,12 @@
             assertSwitch(new Tag(k, "something"), new Tag(k, "something"));
         }
+        // direction=forward/backward/...
+        assertSwitch(new Tag("direction", "forward"), new Tag("direction", "backward"));
+        assertSwitch(new Tag("direction", "backward"), new Tag("direction", "forward"));
+        assertSwitch(new Tag("direction", "north"), new Tag("direction", "south"));
+        assertSwitch(new Tag("direction", "NNE"), new Tag("direction", "SSW"));
+        assertSwitch(new Tag("direction", "270"), new Tag("direction", "90"));
+        assertSwitch(new Tag("direction", "135"), new Tag("direction", "315"));
+        assertSwitch(new Tag("direction", "337"), new Tag("direction", "157"));
         // :left/:right with oneway (see #10977)
         assertSwitch(new Tag("cycleway:left:oneway", "-1"), new Tag("cycleway:right:oneway", "yes"));
@@ -99,3 +117,21 @@
         Assert.assertEquals(ReverseWayTagCorrector.TagSwitcher.apply(oldTag), newTag);
     }
+
+    /**
+     * Test tag correction on way nodes
+     */
+    @Test
+    public void testSwitchingWayNodes() {
+        final OsmPrimitive n1 = OsmUtils.createPrimitive("node");
+        final OsmPrimitive n2 = OsmUtils.createPrimitive("node direction=SSW");
+        final OsmPrimitive n3 = OsmUtils.createPrimitive("node");
+        final Way w = new Way();
+        Stream.of(n1, n2, n3).map(Node.class::cast).forEach(w::addNode);
+        final Map<OsmPrimitive, List<TagCorrection>> tagCorrections = ReverseWayTagCorrector.getTagCorrectionsMap(w);
+        Assert.assertEquals(1, tagCorrections.size());
+        Assert.assertEquals(Collections.singleton(n2),
+                tagCorrections.keySet());
+        Assert.assertEquals(Collections.singletonList(new TagCorrection("direction", "SSW", "direction", "NNE")),
+                tagCorrections.values().iterator().next());
+    }
 }
