Index: /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 999)
+++ /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 1000)
@@ -12,7 +12,10 @@
 import java.util.regex.Pattern;
 
-import org.openstreetmap.josm.command.ChangePropertyCommand;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmUtils;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
 
@@ -22,31 +25,35 @@
 
 		private final String a;
-
 		private final String b;
-
 		private final Pattern startPattern;
-
 		private final Pattern endPattern;
 
+		private final String SEPARATOR = "[:_]?";
+		
 		public PrefixSuffixSwitcher(String a, String b) {
-			this.a = a;
-			this.b = b;
-			startPattern = Pattern.compile("^(" + a + "|" + b + "):.*",
-			        Pattern.CASE_INSENSITIVE);
-			endPattern = Pattern.compile(".*:(" + a + "|" + b + ")$",
-			        Pattern.CASE_INSENSITIVE);
+            this.a = a;
+            this.b = b;
+            startPattern = Pattern.compile(
+                    "^(" + a + "|" + b + ")" + SEPARATOR,
+                    Pattern.CASE_INSENSITIVE);
+            endPattern = Pattern.compile(
+                    SEPARATOR + "(" + a + "|" + b + ")$",
+                    Pattern.CASE_INSENSITIVE);
 		}
 
 		public String apply(String text) {
 			Matcher m = startPattern.matcher(text);
-			if (!m.matches())
+			if (!m.lookingAt())
 				m = endPattern.matcher(text);
 
-			if (m.matches()) {
+			if (m.lookingAt()) {
 				String leftRight = m.group(1).toLowerCase();
 
-				return text.substring(0, m.start(1)).concat(
-				        leftRight.equals(a) ? b : a).concat(
-				        text.substring(m.end(1)));
+				StringBuilder result = new StringBuilder();
+				result.append(text.substring(0, m.start(1)));
+				result.append(leftRight.equals(a) ? b : a);
+				result.append(text.substring(m.end(1)));
+				
+				return result.toString();
 			}
 			return text;
@@ -54,11 +61,14 @@
 	}
 
-	private static PrefixSuffixSwitcher[] prefixSuffixSwitchers = new PrefixSuffixSwitcher[] {
-	        new PrefixSuffixSwitcher("left", "right"),
-	        new PrefixSuffixSwitcher("forward", "backward") };
+	private static PrefixSuffixSwitcher[] prefixSuffixSwitchers = 
+	        new PrefixSuffixSwitcher[] {
+	            new PrefixSuffixSwitcher("left", "right"),
+	            new PrefixSuffixSwitcher("forward", "backward") 
+	        };
 
-	@Override public Collection<ChangePropertyCommand> execute(Way way) {
-
-		Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap = new HashMap<OsmPrimitive, List<TagCorrection>>();
+	@Override
+	public Collection<Command> execute(Way way) throws UserCancelException {
+		Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap = 
+		        new HashMap<OsmPrimitive, List<TagCorrection>>();
 
 		ArrayList<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
@@ -67,5 +77,4 @@
 
 		for (OsmPrimitive primitive : primitives) {
-
 			tagCorrectionsMap.put(primitive, new ArrayList<TagCorrection>());
 
@@ -98,5 +107,31 @@
 		}
 
-		return applyCorrections(tagCorrectionsMap,
+		Map<OsmPrimitive, List<RoleCorrection>> roleCorrectionMap = 
+		        new HashMap<OsmPrimitive, List<RoleCorrection>>();
+		roleCorrectionMap.put(way, new ArrayList<RoleCorrection>());
+
+		for (Relation relation : Main.ds.relations) {
+			for (RelationMember member : relation.members) {
+				if (!member.member.realEqual(way, true)
+				        || member.role.isEmpty())
+					continue;
+
+				boolean found = false;
+				String newRole = null;
+				for (PrefixSuffixSwitcher prefixSuffixSwitcher : prefixSuffixSwitchers) {
+					newRole = prefixSuffixSwitcher.apply(member.role);
+					if (!newRole.equals(member.role)) {
+						found = true;
+						break;
+					}
+				}
+
+				if (found)
+					roleCorrectionMap.get(way).add(
+					        new RoleCorrection(relation, member, newRole));
+			}
+		}
+
+		return applyCorrections(tagCorrectionsMap, roleCorrectionMap,
 		        tr("When reverting this way, following changes to properties "
 		                + "of the way and its nodes are suggested in order "
Index: /trunk/src/org/openstreetmap/josm/corrector/TagCorrection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/TagCorrection.java	(revision 999)
+++ /trunk/src/org/openstreetmap/josm/corrector/TagCorrection.java	(revision 1000)
@@ -2,5 +2,5 @@
 package org.openstreetmap.josm.corrector;
 
-public class TagCorrection {
+public class TagCorrection implements Correction {
 
 	public final String oldKey;
@@ -9,5 +9,6 @@
 	public final String newValue;
 
-	public TagCorrection(String oldKey, String oldValue, String newKey, String newValue) {
+	public TagCorrection(String oldKey, String oldValue, String newKey,
+            String newValue) {
 		this.oldKey = oldKey;
 		this.oldValue = oldValue;
Index: /trunk/src/org/openstreetmap/josm/corrector/TagCorrectionTable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/TagCorrectionTable.java	(revision 999)
+++ /trunk/src/org/openstreetmap/josm/corrector/TagCorrectionTable.java	(revision 1000)
@@ -2,62 +2,11 @@
 package org.openstreetmap.josm.corrector;
 
-import java.awt.Dimension;
 import java.util.List;
 
-import javax.swing.JTable;
-import javax.swing.JLabel;
-import javax.swing.table.TableCellRenderer;
-import java.awt.Component;
-import java.awt.Font;
+public class TagCorrectionTable extends
+        CorrectionTable<TagCorrectionTableModel> {
 
-public class TagCorrectionTable extends JTable {
-
-	public static class BoldRenderer extends JLabel implements TableCellRenderer {
-
-		public Component getTableCellRendererComponent(JTable table,
-		        Object value, boolean isSelected, boolean hasFocus, int row,
-		        int column) {
-
-			Font f = getFont();
-			setFont(new Font(f.getName(), f.getStyle() | Font.BOLD, f.getSize()));
-
-			setText((String)value);
-
-			return this;
-		}
-	}
-
-	private static TableCellRenderer boldRenderer = null;
-
-	public static TagCorrectionTable create(List<TagCorrection> tagCorrections) {
-		TagCorrectionTableModel tagCorrectionTableModel = new TagCorrectionTableModel(tagCorrections);
-		TagCorrectionTable table = new TagCorrectionTable(
-		        tagCorrectionTableModel);
-		int lines = tagCorrections.size() > 10 ? 10 : tagCorrections.size();  
-		table.setPreferredScrollableViewportSize(new Dimension(400, lines * table.getRowHeight()));
-		table.getColumnModel().getColumn(4).setPreferredWidth(40);
-		table.setRowSelectionAllowed(false);
-
-		return table;
-	}
-
-	public TableCellRenderer getCellRenderer(int row, int column) {
-		TagCorrection tagCorrection = getTagCorrectionTableModel().tagCorrections
-		        .get(row);
-		if ((column == 2 && tagCorrection.isKeyChanged())
-		        || (column == 3 && tagCorrection.isValueChanged())) {
-			if (boldRenderer == null)
-				boldRenderer = new BoldRenderer();
-			return boldRenderer;
-		}
-		return super.getCellRenderer(row, column);
-	}
-
-	private TagCorrectionTable(TagCorrectionTableModel tagCorrectionTableModel) {
-		super(tagCorrectionTableModel);
-	}
-
-	public TagCorrectionTableModel getTagCorrectionTableModel() {
-		return (TagCorrectionTableModel) getModel();
+	public TagCorrectionTable(List<TagCorrection> tagCorrections) {
+		super(new TagCorrectionTableModel(tagCorrections));
 	}
 
Index: /trunk/src/org/openstreetmap/josm/corrector/TagCorrectionTableModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/TagCorrectionTableModel.java	(revision 999)
+++ /trunk/src/org/openstreetmap/josm/corrector/TagCorrectionTableModel.java	(revision 1000)
@@ -4,32 +4,19 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.util.Arrays;
 import java.util.List;
 
-import javax.swing.table.AbstractTableModel;
-
-public class TagCorrectionTableModel extends AbstractTableModel {
-
-	List<TagCorrection> tagCorrections;
-
-	private boolean[] apply;
+public class TagCorrectionTableModel extends CorrectionTableModel<TagCorrection> {
 
 	public TagCorrectionTableModel(List<TagCorrection> tagCorrections) {
-		this.tagCorrections = tagCorrections;
-		apply = new boolean[this.tagCorrections.size()];
-		Arrays.fill(apply, true);
+		super(tagCorrections);
 	}
 
+	@Override
 	public int getColumnCount() {
 		return 5;
 	}
 
-	@Override public Class<?> getColumnClass(int columnIndex) {
-		if (columnIndex == 4)
-			return Boolean.class;
-		return String.class;
-	}
-
-	@Override public String getColumnName(int colIndex) {
+	@Override
+	public String getCorrectionColumnName(int colIndex) {
 		switch (colIndex) {
 		case 0:
@@ -41,17 +28,10 @@
 		case 3:
 			return tr("New value");
-		case 4:
-			return tr("Apply?");
 		}
 		return null;
 	}
 
-	public int getRowCount() {
-		return tagCorrections.size();
-	}
-
-	public Object getValueAt(int rowIndex, int colIndex) {
-
-		TagCorrection tagCorrection = tagCorrections.get(rowIndex);
+    public Object getCorrectionValueAt(int rowIndex, int colIndex) {
+		TagCorrection tagCorrection = getCorrections().get(rowIndex);
 
 		switch (colIndex) {
@@ -64,22 +44,13 @@
 		case 3:
 			return tagCorrection.newValue;
-		case 4:
-			return apply[rowIndex];
 		}
 		return null;
 	}
 
-	@Override public boolean isCellEditable(int rowIndex, int columnIndex) {
-		return columnIndex == 4;
+	protected boolean isBoldCell(int row, int column) {
+		TagCorrection tagCorrection = getCorrections().get(row);
+		return (column == 2 && tagCorrection.isKeyChanged())
+		        || (column == 3 && tagCorrection.isValueChanged());
 	}
 
-	@Override public void setValueAt(Object aValue, int rowIndex,
-	        int columnIndex) {
-		if (columnIndex == 4 && aValue instanceof Boolean)
-			apply[rowIndex] = (Boolean)aValue;
-	}
-
-	public boolean getApply(int i) {
-		return apply[i];
-	}
 }
Index: /trunk/src/org/openstreetmap/josm/corrector/TagCorrector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/TagCorrector.java	(revision 999)
+++ /trunk/src/org/openstreetmap/josm/corrector/TagCorrector.java	(revision 1000)
@@ -18,6 +18,10 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.ChangeCommand;
 import org.openstreetmap.josm.command.ChangePropertyCommand;
+import org.openstreetmap.josm.command.Command;
 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.data.osm.visitor.NameVisitor;
 import org.openstreetmap.josm.gui.JMultilineLabel;
@@ -26,9 +30,17 @@
 public abstract class TagCorrector<P extends OsmPrimitive> {
 
-	public abstract Collection<ChangePropertyCommand> execute(P primitive);
+	public abstract Collection<Command> execute(P primitive) 
+	    throws UserCancelException;
 
-	protected Collection<ChangePropertyCommand> applyCorrections(
+    private String[] applicationOptions = new String[] { 
+        tr("Apply selected changes"), 
+        tr("Don't apply changes"), 
+        tr("Cancel") 
+    };
+    
+	protected Collection<Command> applyCorrections(
 	        Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap,
-	        String description) {
+	        Map<OsmPrimitive, List<RoleCorrection>> roleCorrectionMap,
+	        String description) throws UserCancelException {
 
 		boolean hasCorrections = false;
@@ -40,7 +52,20 @@
 		}
 
+		if (!hasCorrections)
+			for (List<RoleCorrection> roleCorrectionList : roleCorrectionMap
+			        .values()) {
+				if (!roleCorrectionList.isEmpty()) {
+					hasCorrections = true;
+					break;
+				}
+			}
+
 		if (hasCorrections) {
-			Collection<ChangePropertyCommand> changePropertyCommands = new ArrayList<ChangePropertyCommand>();
-			Map<OsmPrimitive, TagCorrectionTable> tableMap = new HashMap<OsmPrimitive, TagCorrectionTable>();
+			Collection<Command> commands = new ArrayList<Command>();
+			Map<OsmPrimitive, TagCorrectionTable> tagTableMap = 
+			    new HashMap<OsmPrimitive, TagCorrectionTable>();
+			Map<OsmPrimitive, RoleCorrectionTable> roleTableMap = 
+			    new HashMap<OsmPrimitive, RoleCorrectionTable>();
+
 			NameVisitor nameVisitor = new NameVisitor();
 
@@ -63,44 +88,89 @@
 					continue;
 
-				final TagCorrectionTable table = TagCorrectionTable
-				        .create(tagCorrections);
+				primitive.visit(nameVisitor);
+
+				final JLabel propertiesLabel = new JLabel(tr("Properties of "));
+				p.add(propertiesLabel, GBC.std());
+
+				final JLabel primitiveLabel = new JLabel(
+				        nameVisitor.name + ":", nameVisitor.icon, JLabel.LEFT);
+				p.add(primitiveLabel, GBC.eol());
+
+				final TagCorrectionTable table = new TagCorrectionTable(
+				        tagCorrections);
 				final JScrollPane scrollPane = new JScrollPane(table);
-				tableMap.put(primitive, table);
+				p.add(scrollPane, GBC.eop());
+
+				tagTableMap.put(primitive, table);
+			}
+
+			for (OsmPrimitive primitive : roleCorrectionMap.keySet()) {
+				final List<RoleCorrection> roleCorrections = roleCorrectionMap
+				        .get(primitive);
+				if (roleCorrections.isEmpty())
+					continue;
 
 				primitive.visit(nameVisitor);
 
-				final JLabel label3 = new JLabel(nameVisitor.name + ":",
-				        nameVisitor.icon, JLabel.LEFT);
+				final JLabel rolesLabel = new JLabel(
+				        tr("Roles in relations refering to"));
+				p.add(rolesLabel, GBC.std());
 
-				p.add(label3, GBC.eol());
+				final JLabel primitiveLabel = new JLabel(
+				        nameVisitor.name + ":", nameVisitor.icon, JLabel.LEFT);
+				p.add(primitiveLabel, GBC.eol());
+
+				final RoleCorrectionTable table = new RoleCorrectionTable(
+				        roleCorrections);
+				final JScrollPane scrollPane = new JScrollPane(table);
 				p.add(scrollPane, GBC.eop());
+
+				roleTableMap.put(primitive, table);
 			}
 
-			int answer = JOptionPane.showConfirmDialog(Main.parent, p,
-			        tr("Automatic tag correction"),
-			        JOptionPane.OK_CANCEL_OPTION);
+			int answer = JOptionPane.showOptionDialog(Main.parent, p,
+                    tr("Automatic tag correction"), JOptionPane.YES_NO_CANCEL_OPTION,
+                    JOptionPane.PLAIN_MESSAGE, null, 
+                    applicationOptions, applicationOptions[0]);
 
-			if (answer == JOptionPane.OK_OPTION) {
+			if (answer == JOptionPane.YES_OPTION) {
 				for (OsmPrimitive primitive : tagCorrectionsMap.keySet()) {
 					List<TagCorrection> tagCorrections = tagCorrectionsMap
 					        .get(primitive);
 					for (int i = 0; i < tagCorrections.size(); i++) {
-						if (tableMap.get(primitive)
-						        .getTagCorrectionTableModel().getApply(i)) {
+						if (tagTableMap.get(primitive)
+						        .getCorrectionTableModel().getApply(i)) {
 							TagCorrection tagCorrection = tagCorrections.get(i);
 							if (tagCorrection.isKeyChanged())
-								changePropertyCommands
-								        .add(new ChangePropertyCommand(
-								                primitive,
-								                tagCorrection.oldKey, null));
-							changePropertyCommands
-							        .add(new ChangePropertyCommand(primitive,
-							                tagCorrection.newKey,
-							                tagCorrection.newValue));
+								commands.add(new ChangePropertyCommand(
+								        primitive, tagCorrection.oldKey, null));
+							commands.add(new ChangePropertyCommand(primitive,
+							        tagCorrection.newKey,
+							        tagCorrection.newValue));
 						}
 					}
 				}
+				for (OsmPrimitive primitive : roleCorrectionMap.keySet()) {
+					List<RoleCorrection> roleCorrections = roleCorrectionMap
+					        .get(primitive);
+					for (int i = 0; i < roleCorrections.size(); i++) {
+						if (roleTableMap.get(primitive)
+						        .getCorrectionTableModel().getApply(i)) {
+							RoleCorrection roleCorrection = roleCorrections
+							        .get(i);
+							Relation newRelation = new Relation(
+							        roleCorrection.relation);
+							for (RelationMember member : newRelation.members)
+								if (member.equals(roleCorrection.member))
+									member.role = roleCorrection.newRole;
+							commands.add(new ChangeCommand(
+							        roleCorrection.relation, newRelation));
+						}
+					}
+				}
+			} else if (answer != JOptionPane.NO_OPTION) {
+			    throw new UserCancelException();
 			}
-			return changePropertyCommands;
+			return commands;
 		}
 
