diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java b/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
index b0b2aad..671a513 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
@@ -23,6 +23,7 @@ import java.awt.event.MouseEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -48,7 +49,6 @@ import javax.swing.JToolBar;
 import javax.swing.KeyStroke;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.ExpertToggleAction;
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.command.ChangeCommand;
 import org.openstreetmap.josm.command.Command;
@@ -75,6 +75,8 @@ import org.openstreetmap.josm.gui.dialogs.relation.actions.DownloadIncompleteMem
 import org.openstreetmap.josm.gui.dialogs.relation.actions.DownloadSelectedIncompleteMembersAction;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.DuplicateRelationAction;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.EditAction;
+import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionAccess;
+import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionGroup;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.MoveDownAction;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.MoveUpAction;
 import org.openstreetmap.josm.gui.dialogs.relation.actions.OKAction;
@@ -92,6 +94,7 @@ import org.openstreetmap.josm.gui.dialogs.relation.actions.SortBelowAction;
 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
@@ -220,12 +223,12 @@ public class GenericRelationEditor extends RelationEditor {
         selectionTable = new SelectionTable(selectionTableModel, memberTableModel);
         selectionTable.setRowHeight(ce.getEditor().getPreferredSize().height);
 
-        leftButtonToolbar = new LeftButtonToolbar(memberTable, memberTableModel, this);
+        leftButtonToolbar = new LeftButtonToolbar(new RelationEditorActionAccess());
         tfRole = buildRoleTextField(this);
 
         JSplitPane pane = buildSplitPane(
                 buildTagEditorPanel(tagEditorPanel),
-                buildMemberEditorPanel(memberTable, memberTableModel, selectionTable, selectionTableModel, this, leftButtonToolbar, tfRole),
+                buildMemberEditorPanel(leftButtonToolbar, new RelationEditorActionAccess()),
                 this);
         pane.setPreferredSize(new Dimension(100, 100));
 
@@ -247,16 +250,18 @@ public class GenericRelationEditor extends RelationEditor {
                 referrerBrowser.init();
             }
         });
-
-        refreshAction = new RefreshAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
-        applyAction = new ApplyAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
-        selectAction = new SelectAction(getLayer(), this);
-        duplicateAction = new DuplicateRelationAction(memberTableModel, tagEditorPanel.getModel(), getLayer());
-        deleteAction = new DeleteCurrentRelationAction(getLayer(), this);
+        
+        IRelationEditorActionAccess actionAccess = new RelationEditorActionAccess();
+
+        refreshAction = new RefreshAction(actionAccess);
+        applyAction = new ApplyAction(actionAccess);
+        selectAction = new SelectAction(actionAccess);
+        duplicateAction = new DuplicateRelationAction(actionAccess);
+        deleteAction = new DeleteCurrentRelationAction(actionAccess);
         addPropertyChangeListener(deleteAction);
 
-        okAction = new OKAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
-        cancelAction = new CancelAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
+        okAction = new OKAction(actionAccess);
+        cancelAction = new CancelAction(actionAccess);
 
         getContentPane().add(buildToolBar(refreshAction, applyAction, selectAction, duplicateAction, deleteAction), BorderLayout.NORTH);
         getContentPane().add(tabbedPane, BorderLayout.CENTER);
@@ -287,8 +292,10 @@ public class GenericRelationEditor extends RelationEditor {
         KeyStroke key = Shortcut.getPasteKeyStroke();
         if (key != null) {
             // handle uncommon situation, that user has no keystroke assigned to paste
-            registerCopyPasteAction(new PasteMembersAction(memberTable, getLayer(), this) {
-                @Override
+            registerCopyPasteAction(new PasteMembersAction(actionAccess) {
+				private static final long serialVersionUID = 1L;
+
+				@Override
                 public void actionPerformed(ActionEvent e) {
                     super.actionPerformed(e);
                     tfRole.requestFocusInWindow();
@@ -298,7 +305,7 @@ public class GenericRelationEditor extends RelationEditor {
         key = Shortcut.getCopyKeyStroke();
         if (key != null) {
             // handle uncommon situation, that user has no keystroke assigned to copy
-            registerCopyPasteAction(new CopyMembersAction(memberTableModel, getLayer(), this),
+            registerCopyPasteAction(new CopyMembersAction(actionAccess),
                     "COPY_MEMBERS", key, getRootPane(), memberTable, selectionTable);
         }
         tagEditorPanel.setNextFocusComponent(memberTable);
@@ -446,21 +453,15 @@ public class GenericRelationEditor extends RelationEditor {
 
     /**
      * builds the panel for the relation member editor
-     * @param memberTable member table
-     * @param memberTableModel member table model
-     * @param selectionTable selection table
-     * @param selectionTableModel selection table model
-     * @param re relation editor
      * @param leftButtonToolbar left button toolbar
-     * @param tfRole role text field
+     * @param editorAccess The relation editor
      *
      * @return the panel for the relation member editor
      */
-    protected static JPanel buildMemberEditorPanel(final MemberTable memberTable, MemberTableModel memberTableModel,
-            SelectionTable selectionTable, SelectionTableModel selectionTableModel, IRelationEditor re,
-            LeftButtonToolbar leftButtonToolbar, final AutoCompletingTextField tfRole) {
+    protected static JPanel buildMemberEditorPanel(
+            LeftButtonToolbar leftButtonToolbar, IRelationEditorActionAccess editorAccess) {
         final JPanel pnl = new JPanel(new GridBagLayout());
-        final JScrollPane scrollPane = new JScrollPane(memberTable);
+        final JScrollPane scrollPane = new JScrollPane(editorAccess.getMemberTable());
 
         GridBagConstraints gc = new GridBagConstraints();
         gc.gridx = 0;
@@ -494,15 +495,15 @@ public class GenericRelationEditor extends RelationEditor {
         // --- role editing
         JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
         p3.add(new JLabel(tr("Apply Role:")));
-        p3.add(tfRole);
-        SetRoleAction setRoleAction = new SetRoleAction(memberTable, memberTableModel, tfRole);
-        memberTableModel.getSelectionModel().addListSelectionListener(setRoleAction);
-        tfRole.getDocument().addDocumentListener(setRoleAction);
-        tfRole.addActionListener(setRoleAction);
-        memberTableModel.getSelectionModel().addListSelectionListener(
-                e -> tfRole.setEnabled(memberTable.getSelectedRowCount() > 0)
+        p3.add(editorAccess.getTextFieldRole());
+        SetRoleAction setRoleAction = new SetRoleAction(editorAccess);
+        editorAccess.getMemberTableModel().getSelectionModel().addListSelectionListener(setRoleAction);
+        editorAccess.getTextFieldRole().getDocument().addDocumentListener(setRoleAction);
+        editorAccess.getTextFieldRole().addActionListener(setRoleAction);
+        editorAccess.getMemberTableModel().getSelectionModel().addListSelectionListener(
+                e -> editorAccess.getTextFieldRole().setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0)
         );
-        tfRole.setEnabled(memberTable.getSelectedRowCount() > 0);
+        editorAccess.getTextFieldRole().setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0);
         JButton btnApply = new JButton(setRoleAction);
         btnApply.setPreferredSize(new Dimension(20, 20));
         btnApply.setText("");
@@ -536,7 +537,7 @@ public class GenericRelationEditor extends RelationEditor {
         gc.anchor = GridBagConstraints.NORTHWEST;
         gc.weightx = 0.0;
         gc.weighty = 1.0;
-        pnl2.add(new ScrollViewport(buildSelectionControlButtonToolbar(memberTable, memberTableModel, selectionTableModel, re),
+        pnl2.add(new ScrollViewport(buildSelectionControlButtonToolbar(editorAccess),
                 ScrollViewport.VERTICAL_DIRECTION), gc);
 
         gc.gridx = 1;
@@ -544,14 +545,14 @@ public class GenericRelationEditor extends RelationEditor {
         gc.weightx = 1.0;
         gc.weighty = 1.0;
         gc.fill = GridBagConstraints.BOTH;
-        pnl2.add(buildSelectionTablePanel(selectionTable), gc);
+        pnl2.add(buildSelectionTablePanel(editorAccess.getSelectionTable()), gc);
 
         final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
         splitPane.setLeftComponent(pnl);
         splitPane.setRightComponent(pnl2);
         splitPane.setOneTouchExpandable(false);
-        if (re instanceof Window) {
-            ((Window) re).addWindowListener(new WindowAdapter() {
+        if (editorAccess.getEditor() instanceof Window) {
+            ((Window) editorAccess.getEditor()).addWindowListener(new WindowAdapter() {
                 @Override
                 public void windowOpened(WindowEvent e) {
                     // has to be called when the window is visible, otherwise no effect
@@ -607,79 +608,52 @@ public class GenericRelationEditor extends RelationEditor {
      * The toolbar with the buttons on the left
      */
     static class LeftButtonToolbar extends JToolBar {
+		private static final long serialVersionUID = 1L;
 
-        /**
-         * Button for performing the {@link org.openstreetmap.josm.gui.dialogs.relation.actions.SortBelowAction}.
-         */
-        final JButton sortBelowButton;
-
-        /**
+		/**
          * Constructs a new {@code LeftButtonToolbar}.
-         * @param memberTable member table
-         * @param memberTableModel member table model
          * @param re relation editor
          */
-        LeftButtonToolbar(MemberTable memberTable, MemberTableModel memberTableModel, IRelationEditor re) {
+        LeftButtonToolbar(IRelationEditorActionAccess editorAccess) {
             setOrientation(JToolBar.VERTICAL);
             setFloatable(false);
 
-            // -- move up action
-            MoveUpAction moveUpAction = new MoveUpAction(memberTable, memberTableModel, "moveUp");
-            memberTableModel.getSelectionModel().addListSelectionListener(moveUpAction);
-            add(moveUpAction);
-
-            // -- move down action
-            MoveDownAction moveDownAction = new MoveDownAction(memberTable, memberTableModel, "moveDown");
-            memberTableModel.getSelectionModel().addListSelectionListener(moveDownAction);
-            add(moveDownAction);
-
-            addSeparator();
-
-            // -- edit action
-            EditAction editAction = new EditAction(memberTable, memberTableModel, re.getLayer());
-            memberTableModel.getSelectionModel().addListSelectionListener(editAction);
-            add(editAction);
-
-            // -- delete action
-            RemoveAction removeSelectedAction = new RemoveAction(memberTable, memberTableModel, "removeSelected");
-            memberTable.getSelectionModel().addListSelectionListener(removeSelectedAction);
-            add(removeSelectedAction);
-
-            addSeparator();
-            // -- sort action
-            SortAction sortAction = new SortAction(memberTable, memberTableModel);
-            memberTableModel.addTableModelListener(sortAction);
-            add(sortAction);
-            final SortBelowAction sortBelowAction = new SortBelowAction(memberTable, memberTableModel);
-            memberTableModel.addTableModelListener(sortBelowAction);
-            memberTableModel.getSelectionModel().addListSelectionListener(sortBelowAction);
-            sortBelowButton = add(sortBelowAction);
-
-            // -- reverse action
-            ReverseAction reverseAction = new ReverseAction(memberTable, memberTableModel);
-            memberTableModel.addTableModelListener(reverseAction);
-            add(reverseAction);
-
-            addSeparator();
-
-            // -- download action
-            DownloadIncompleteMembersAction downloadIncompleteMembersAction = new DownloadIncompleteMembersAction(
-                    memberTable, memberTableModel, "downloadIncomplete", re.getLayer(), re);
-            memberTable.getModel().addTableModelListener(downloadIncompleteMembersAction);
-            add(downloadIncompleteMembersAction);
-
-            // -- download selected action
-            DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembersAction = new DownloadSelectedIncompleteMembersAction(
-                    memberTable, memberTableModel, null, re.getLayer(), re);
-            memberTable.getModel().addTableModelListener(downloadSelectedIncompleteMembersAction);
-            memberTable.getSelectionModel().addListSelectionListener(downloadSelectedIncompleteMembersAction);
-            add(downloadSelectedIncompleteMembersAction);
-
-            InputMap inputMap = memberTable.getInputMap(MemberTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
-            inputMap.put((KeyStroke) removeSelectedAction.getValue(AbstractAction.ACCELERATOR_KEY), "removeSelected");
-            inputMap.put((KeyStroke) moveUpAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveUp");
-            inputMap.put((KeyStroke) moveDownAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveDown");
-            inputMap.put((KeyStroke) downloadIncompleteMembersAction.getValue(AbstractAction.ACCELERATOR_KEY), "downloadIncomplete");
+            List<IRelationEditorActionGroup> groups = new ArrayList<>();
+            // Move
+            groups.add(buildNativeGroup(10,
+            		new MoveUpAction(editorAccess, "moveUp"),
+            		new MoveDownAction(editorAccess, "moveDown")
+            		));
+            // Edit
+            groups.add(buildNativeGroup(20,
+            		new EditAction(editorAccess),
+            		new RemoveAction(editorAccess, "removeSelected")
+            		));
+            // Sort
+            groups.add(buildNativeGroup(30,
+            		new SortAction(editorAccess),
+            		new SortBelowAction(editorAccess)
+            		));
+            // Reverse
+            groups.add(buildNativeGroup(40,
+            		new ReverseAction(editorAccess)
+            		));
+            // Download
+            groups.add(buildNativeGroup(50,
+            		new DownloadIncompleteMembersAction(editorAccess, "downloadIncomplete"),
+            		new DownloadSelectedIncompleteMembersAction(editorAccess)
+            		));
+            groups.addAll(RelationEditorHooks.getMemberActions());
+            
+            IRelationEditorActionGroup.fillToolbar(this, groups, editorAccess);
+            
+
+            InputMap inputMap = editorAccess.getMemberTable().getInputMap(MemberTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+            inputMap.put((KeyStroke) new RemoveAction(editorAccess, "removeSelected").getValue(AbstractAction.ACCELERATOR_KEY), "removeSelected");
+            inputMap.put((KeyStroke) new MoveUpAction(editorAccess, "moveUp").getValue(AbstractAction.ACCELERATOR_KEY), "moveUp");
+            inputMap.put((KeyStroke) new MoveDownAction(editorAccess, "moveDown").getValue(AbstractAction.ACCELERATOR_KEY), "moveDown");
+            inputMap.put((KeyStroke) new DownloadIncompleteMembersAction(
+            		editorAccess, "downloadIncomplete").getValue(AbstractAction.ACCELERATOR_KEY), "downloadIncomplete");
         }
     }
 
@@ -692,61 +666,43 @@ public class GenericRelationEditor extends RelationEditor {
      *
      * @return control buttons panel for selection/members
      */
-    protected static JToolBar buildSelectionControlButtonToolbar(MemberTable memberTable,
-            MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor re) {
+    protected static JToolBar buildSelectionControlButtonToolbar(IRelationEditorActionAccess editorAccess) {
         JToolBar tb = new JToolBar(JToolBar.VERTICAL);
         tb.setFloatable(false);
 
-        // -- add at start action
-        AddSelectedAtStartAction addSelectionAction = new AddSelectedAtStartAction(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectionAction);
-        tb.add(addSelectionAction);
-
-        // -- add before selected action
-        AddSelectedBeforeSelection addSelectedBeforeSelectionAction = new AddSelectedBeforeSelection(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectedBeforeSelectionAction);
-        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedBeforeSelectionAction);
-        tb.add(addSelectedBeforeSelectionAction);
-
-        // -- add after selected action
-        AddSelectedAfterSelection addSelectedAfterSelectionAction = new AddSelectedAfterSelection(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectedAfterSelectionAction);
-        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedAfterSelectionAction);
-        tb.add(addSelectedAfterSelectionAction);
-
-        // -- add at end action
-        AddSelectedAtEndAction addSelectedAtEndAction = new AddSelectedAtEndAction(
-                memberTableModel, selectionTableModel, re);
-        selectionTableModel.addTableModelListener(addSelectedAtEndAction);
-        tb.add(addSelectedAtEndAction);
-
-        tb.addSeparator();
-
-        // -- select members action
-        SelectedMembersForSelectionAction selectMembersForSelectionAction = new SelectedMembersForSelectionAction(
-                memberTableModel, selectionTableModel, re.getLayer());
-        selectionTableModel.addTableModelListener(selectMembersForSelectionAction);
-        memberTableModel.addTableModelListener(selectMembersForSelectionAction);
-        tb.add(selectMembersForSelectionAction);
-
-        // -- select action
-        SelectPrimitivesForSelectedMembersAction selectAction = new SelectPrimitivesForSelectedMembersAction(
-                memberTable, memberTableModel, re.getLayer());
-        memberTable.getSelectionModel().addListSelectionListener(selectAction);
-        tb.add(selectAction);
-
-        tb.addSeparator();
-
-        // -- remove selected action
-        RemoveSelectedAction removeSelectedAction = new RemoveSelectedAction(memberTableModel, selectionTableModel, re.getLayer());
-        selectionTableModel.addTableModelListener(removeSelectedAction);
-        tb.add(removeSelectedAction);
-
+		List<IRelationEditorActionGroup> groups = new ArrayList<>();
+		groups.add(buildNativeGroup(10,
+				new AddSelectedAtStartAction(editorAccess),
+				new AddSelectedBeforeSelection(editorAccess),
+				new AddSelectedAfterSelection(editorAccess),
+				new AddSelectedAtEndAction(editorAccess)
+				));
+		groups.add(buildNativeGroup(20,
+				new SelectedMembersForSelectionAction(editorAccess),
+				new SelectPrimitivesForSelectedMembersAction(editorAccess)
+				));
+		groups.add(buildNativeGroup(30,
+				new RemoveSelectedAction(editorAccess)
+				));
+		groups.addAll(RelationEditorHooks.getSelectActions());
+        
+        IRelationEditorActionGroup.fillToolbar(tb, groups, editorAccess);
         return tb;
     }
+    
+    private static IRelationEditorActionGroup buildNativeGroup(int order, AbstractRelationEditorAction... actions) {
+    	return new IRelationEditorActionGroup() {
+    		@Override
+    		public int order() {
+    			return order;
+    		}
+    		
+			@Override
+			public List<AbstractRelationEditorAction> getActions(IRelationEditorActionAccess editorAccess) {
+				return Arrays.asList(actions);
+			}
+		};
+    }
 
     @Override
     protected Dimension findMaxDialogSize() {
@@ -764,7 +720,6 @@ public class GenericRelationEditor extends RelationEditor {
         super.setVisible(visible);
         Clipboard clipboard = ClipboardUtils.getClipboard();
         if (visible) {
-            leftButtonToolbar.sortBelowButton.setVisible(ExpertToggleAction.isExpert());
             RelationDialogManager.getRelationDialogManager().positionOnScreen(this);
             if (windowMenuItem == null) {
                 windowMenuItem = addToWindowMenu(this, getLayer().getName());
@@ -805,7 +760,9 @@ public class GenericRelationEditor extends RelationEditor {
                 "dialogs/relationlist",
                 tr("Focus Relation Editor with relation ''{0}'' in layer ''{1}''", name, layerName),
                 null, false, false) {
-            @Override
+			private static final long serialVersionUID = 1L;
+
+			@Override
             public void actionPerformed(ActionEvent e) {
                 ((RelationEditor) getValue("relationEditor")).setVisible(true);
             }
@@ -987,8 +944,47 @@ public class GenericRelationEditor extends RelationEditor {
         @Override
         public void mouseClicked(MouseEvent e) {
             if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
-                new EditAction(memberTable, memberTableModel, getLayer()).actionPerformed(null);
+                new EditAction(new RelationEditorActionAccess()).actionPerformed(null);
             }
         }
     }
+    
+    private class RelationEditorActionAccess implements IRelationEditorActionAccess {
+
+		@Override
+		public MemberTable getMemberTable() {
+			return memberTable;
+		}
+
+		@Override
+		public MemberTableModel getMemberTableModel() {
+			return memberTableModel;
+		}
+
+		@Override
+		public SelectionTable getSelectionTable() {
+			return selectionTable;
+		}
+
+		@Override
+		public SelectionTableModel getSelectionTableModel() {
+			return selectionTableModel;
+		}
+
+		@Override
+		public IRelationEditor getEditor() {
+			return GenericRelationEditor.this;
+		}
+
+		@Override
+		public TagEditorModel getTagModel() {
+			return tagEditorPanel.getModel();
+		}
+
+		@Override
+		public AutoCompletingTextField getTextFieldRole() {
+			return tfRole;
+		}
+    	
+    }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java
index cb2747a..0d17216 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java
@@ -5,10 +5,7 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -16,15 +13,15 @@ import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.Logging;
 
 /**
  * Abstract relation editor.
  * @since 1599
  */
 public abstract class RelationEditor extends ExtendedDialog implements IRelationEditor {
+	private static final long serialVersionUID = 1L;
 
-    /** the property name for the current relation.
+	/** the property name for the current relation.
      * @see #setRelation(Relation)
      * @see #getRelation()
      */
@@ -35,9 +32,6 @@ public abstract class RelationEditor extends ExtendedDialog implements IRelation
      */
     public static final String RELATION_SNAPSHOT_PROP = RelationEditor.class.getName() + ".relationSnapshot";
 
-    /** the list of registered relation editor classes */
-    private static List<Class<RelationEditor>> editors = new ArrayList<>();
-
     /** The relation that this editor is working on. */
     private transient Relation relation;
 
@@ -70,28 +64,10 @@ public abstract class RelationEditor extends ExtendedDialog implements IRelation
     }
 
     /**
-     * Registers a relation editor class. Depending on the type of relation to be edited
-     * {@link #getEditor(OsmDataLayer, Relation, Collection)} will create an instance of
-     * this class.
-     *
-     * @param clazz the class
-     */
-    public void registerRelationEditor(Class<RelationEditor> clazz) {
-        if (clazz != null && !editors.contains(clazz)) {
-            editors.add(clazz);
-        }
-    }
-
-    /**
      * This is a factory method that creates an appropriate RelationEditor instance suitable for editing the relation
      * that was passed in as an argument.
      *
-     * This method is guaranteed to return a working RelationEditor. If no specific editor has been registered for the
-     * type of relation, then a generic editor will be returned.
-     *
-     * Editors can be registered by adding their class to the static list "editors" in the RelationEditor class.
-     * When it comes to editing a relation, all registered editors are queried via their static "canEdit" method whether
-     * they feel responsible for that kind of relation, and if they return true then an instance of that class will be used.
+     * This method is guaranteed to return a working RelationEditor.
      *
      * @param layer the data layer the relation is a member of
      * @param r the relation to be edited
@@ -99,17 +75,6 @@ public abstract class RelationEditor extends ExtendedDialog implements IRelation
      * @return an instance of RelationEditor suitable for editing that kind of relation
      */
     public static RelationEditor getEditor(OsmDataLayer layer, Relation r, Collection<RelationMember> selectedMembers) {
-        for (Class<RelationEditor> e : editors) {
-            try {
-                Method m = e.getMethod("canEdit", Relation.class);
-                Boolean canEdit = (Boolean) m.invoke(null, r);
-                if (canEdit) {
-                    return e.getConstructor(Relation.class, Collection.class).newInstance(layer, r, selectedMembers);
-                }
-            } catch (ReflectiveOperationException ex) {
-                Logging.warn(ex);
-            }
-        }
         if (RelationDialogManager.getRelationDialogManager().isOpenInEditor(layer, r))
             return RelationDialogManager.getRelationDialogManager().getEditorForRelation(layer, r);
         else {
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditorHooks.java b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditorHooks.java
new file mode 100644
index 0000000..d8f6fb8
--- /dev/null
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditorHooks.java
@@ -0,0 +1,48 @@
+package org.openstreetmap.josm.gui.dialogs.relation;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionGroup;
+
+/**
+ * This class allows to hook into the relation editor. It can be used to overwrite specific behavior.
+ * 
+ * @author Michael Zangl
+ * @since xxx
+ */
+public class RelationEditorHooks {
+	
+	private static final CopyOnWriteArrayList<IRelationEditorActionGroup> memberActions = new CopyOnWriteArrayList<>();
+	private static final CopyOnWriteArrayList<IRelationEditorActionGroup> selectionActions = new CopyOnWriteArrayList<>();
+
+	private RelationEditorHooks() {
+		// only static methods.
+	}
+	
+	/**
+	 * Adds actions to the members action toolbar
+	 * @param group The group to add
+	 */
+	public static void addActionsToMembers(IRelationEditorActionGroup group) {
+		memberActions.add(group);
+	}
+	
+	/**
+	 * Adds actions to the selection action toolbar
+	 * @param group The group to add
+	 */
+	public static void addActionsToSelectio(IRelationEditorActionGroup group) {
+		selectionActions.add(group);
+	}
+	
+	/* package */ static List<IRelationEditorActionGroup> getMemberActions() {
+		return Collections.unmodifiableList(memberActions);
+	}
+	
+	/* package */ static List<IRelationEditorActionGroup> getSelectActions() {
+		return Collections.unmodifiableList(selectionActions);
+	}
+	
+}
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java
index a6b6153..e093389 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java
@@ -1,6 +1,10 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.dialogs.relation.actions;
 
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Objects;
+
 import javax.swing.AbstractAction;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -13,51 +17,116 @@ import org.openstreetmap.josm.data.osm.DownloadPolicy;
 import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTable;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.io.OnlineResource;
 
 /**
  * Abstract superclass of relation editor actions.
+ * 
  * @since 9496
  */
-public abstract class AbstractRelationEditorAction extends AbstractAction implements TableModelListener, ListSelectionListener {
-    protected final MemberTable memberTable;
-    protected final MemberTableModel memberTableModel;
-    protected final transient OsmDataLayer layer;
-    protected final transient IRelationEditor editor;
-
-    protected AbstractRelationEditorAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        this(memberTable, memberTableModel, actionMapKey, null, null);
-    }
+public abstract class AbstractRelationEditorAction extends AbstractAction
+		implements TableModelListener, ListSelectionListener, PropertyChangeListener {
+	private static final long serialVersionUID = 1L;
+	protected final transient IRelationEditorActionAccess editorAccess;
 
-    protected AbstractRelationEditorAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey,
-            OsmDataLayer layer, IRelationEditor editor) {
-        this.memberTable = memberTable;
-        this.memberTableModel = memberTableModel;
-        this.layer = layer;
-        this.editor = editor;
-        if (actionMapKey != null) {
-            this.memberTable.getActionMap().put(actionMapKey, this);
-        }
-    }
+	/**
+	 * Create a new relation editor action
+	 * 
+	 * @param editorAccess
+	 *            The editor this action is for
+	 * @param actionMapKey
+	 *            The key for the member table action map.
+	 * @param updateOn
+	 *            The events that may cause the enabled state of this button to
+	 *            change.
+	 */
+	protected AbstractRelationEditorAction(IRelationEditorActionAccess editorAccess,
+			IRelationEditorUpdateOn... updateOn) {
+		Objects.requireNonNull(editorAccess, "editorAccess");
+		Objects.requireNonNull(updateOn, "updateOn");
+		this.editorAccess = editorAccess;
+		for (IRelationEditorUpdateOn u : updateOn) {
+			u.register(editorAccess, this);
+		}
+	}
 
-    @Override
-    public void tableChanged(TableModelEvent e) {
-        updateEnabledState();
-    }
+	/**
+	 * Create a new relation editor action
+	 * 
+	 * @param editorAccess
+	 *            The editor this action is for
+	 * @param actionMapKey
+	 *            The key for the member table action map.
+	 * @param updateOn
+	 *            The events that may cause the enabled state of this button to
+	 *            change.
+	 */
+	protected AbstractRelationEditorAction(IRelationEditorActionAccess editorAccess, String actionMapKey,
+			IRelationEditorUpdateOn... updateOn) {
+		this(editorAccess, updateOn);
+		Objects.requireNonNull(actionMapKey, "actionMapKey");
+
+		this.editorAccess.addMemberTableAction(actionMapKey, this);
+	}
+
+	@Override
+	public void tableChanged(TableModelEvent e) {
+		updateEnabledState();
+	}
+
+	@Override
+	public void valueChanged(ListSelectionEvent e) {
+		updateEnabledState();
+	}
 
     @Override
-    public void valueChanged(ListSelectionEvent e) {
+    public void propertyChange(PropertyChangeEvent evt) {
         updateEnabledState();
     }
 
-    protected abstract void updateEnabledState();
+	protected abstract void updateEnabledState();
 
-    protected final boolean canDownload() {
-        if (editor.getRelation() == null)
-            return false;
-        DataSet ds = editor.getRelation().getDataSet();
-        return !Main.isOffline(OnlineResource.OSM_API)
-            && ds != null && !ds.isLocked() && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy());
-    }
+	protected final boolean canDownload() {
+		if (editorAccess.getEditor().getRelation() == null)
+			return false;
+		DataSet ds = editorAccess.getEditor().getRelation().getDataSet();
+		return !Main.isOffline(OnlineResource.OSM_API) && ds != null && !ds.isLocked()
+				&& !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy());
+	}
+
+	protected MemberTable getMemberTable() {
+		return editorAccess.getMemberTable();
+	}
+
+	protected MemberTableModel getMemberTableModel() {
+		return editorAccess.getMemberTableModel();
+	}
+
+	protected SelectionTable getSelectionTable() {
+		return editorAccess.getSelectionTable();
+	}
+
+	protected SelectionTableModel getSelectionTableModel() {
+		return editorAccess.getSelectionTableModel();
+	}
+
+	protected IRelationEditor getEditor() {
+		return editorAccess.getEditor();
+	}
+
+	protected TagEditorModel getTagModel() {
+		return editorAccess.getTagModel();
+	}
+
+	protected OsmDataLayer getLayer() {
+		return editorAccess.getEditor().getLayer();
+	}
+
+	public boolean isExpertOnly() {
+		return false;
+	}
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java
index 1b0953f..4c6d3fa 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java
@@ -10,31 +10,21 @@ import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor;
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTable;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
  * Abstract superclass of "Add from selection" actions.
  * @since 9496
  */
 abstract class AddFromSelectionAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
-    protected final SelectionTable selectionTable;
-    protected final SelectionTableModel selectionTableModel;
-
-    protected AddFromSelectionAction(MemberTable memberTable, MemberTableModel memberTableModel, SelectionTable selectionTable,
-            SelectionTableModel selectionTableModel, String actionMapKey, OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, memberTableModel, actionMapKey, layer, editor);
-        this.selectionTable = selectionTable;
-        this.selectionTableModel = selectionTableModel;
+    protected AddFromSelectionAction(IRelationEditorActionAccess editorAccess,
+			IRelationEditorUpdateOn... updateOn) {
+        super(editorAccess, updateOn);
     }
 
     protected boolean isPotentialDuplicate(OsmPrimitive primitive) {
-        return memberTableModel.hasMembersReferringTo(Collections.singleton(primitive));
+        return editorAccess.getMemberTableModel().hasMembersReferringTo(Collections.singleton(primitive));
     }
 
     protected List<OsmPrimitive> filterConfirmedPrimitives(List<OsmPrimitive> primitives) throws AddAbortException {
@@ -43,7 +33,7 @@ abstract class AddFromSelectionAction extends AbstractRelationEditorAction {
         List<OsmPrimitive> ret = new ArrayList<>();
         ConditionalOptionPaneUtil.startBulkOperation("add_primitive_to_relation");
         for (OsmPrimitive primitive : primitives) {
-            if (primitive instanceof Relation && editor.getRelation() != null && editor.getRelation().equals(primitive)) {
+            if (primitive instanceof Relation && editorAccess.getEditor().getRelation() != null && editorAccess.getEditor().getRelation().equals(primitive)) {
                 GenericRelationEditor.warnOfCircularReferences(primitive);
                 continue;
             }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java
index ca62de2..74a4ef9 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAfterSelection.java
@@ -6,9 +6,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
 
@@ -17,6 +14,7 @@ import org.openstreetmap.josm.tools.Logging;
  * @since 9496
  */
 public class AddSelectedAfterSelection extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code AddSelectedAfterSelection}.
@@ -24,8 +22,8 @@ public class AddSelectedAfterSelection extends AddFromSelectionAction {
      * @param selectionTableModel selection table model
      * @param editor relation editor
      */
-    public AddSelectedAfterSelection(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedAfterSelection(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset after the last selected member"));
         new ImageProvider("dialogs/conflict", "copyaftercurrentright").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -33,14 +31,15 @@ public class AddSelectedAfterSelection extends AddFromSelectionAction {
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0 && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
+		setEnabled(getSelectionTableModel().getRowCount() > 0
+				&& getMemberTableModel().getSelectionModel().getMinSelectionIndex() >= 0);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersAfterIdx(filterConfirmedPrimitives(selectionTableModel.getSelection()),
-                    memberTableModel.getSelectionModel().getMaxSelectionIndex());
+        	getMemberTableModel().addMembersAfterIdx(filterConfirmedPrimitives(getSelectionTableModel().getSelection()),
+        			getMemberTableModel().getSelectionModel().getMaxSelectionIndex());
         } catch (AddAbortException ex) {
             Logging.trace(ex);
         }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java
index 5e7443f..826ed7d 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtEndAction.java
@@ -6,9 +6,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
 
@@ -17,6 +14,7 @@ import org.openstreetmap.josm.tools.Logging;
  * @since 9496
  */
 public class AddSelectedAtEndAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code AddSelectedAtEndAction}.
@@ -24,8 +22,8 @@ public class AddSelectedAtEndAction extends AddFromSelectionAction {
      * @param selectionTableModel selection table model
      * @param editor relation editor
      */
-    public AddSelectedAtEndAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedAtEndAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset after the last member"));
         new ImageProvider("dialogs/conflict", "copyendright").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -33,13 +31,13 @@ public class AddSelectedAtEndAction extends AddFromSelectionAction {
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0);
+        setEnabled(getSelectionTableModel().getRowCount() > 0);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersAtEnd(filterConfirmedPrimitives(selectionTableModel.getSelection()));
+        	getMemberTableModel().addMembersAtEnd(filterConfirmedPrimitives(getSelectionTableModel().getSelection()));
         } catch (AddAbortException ex) {
             Logging.trace(ex);
         }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java
index 7b61f32..941f7f9 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedAtStartAction.java
@@ -17,6 +17,7 @@ import org.openstreetmap.josm.tools.Logging;
  * @since 9496
  */
 public class AddSelectedAtStartAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code AddSelectedAtStartAction}.
@@ -24,8 +25,8 @@ public class AddSelectedAtStartAction extends AddFromSelectionAction {
      * @param selectionTableModel selection table model
      * @param editor relation editor
      */
-    public AddSelectedAtStartAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedAtStartAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset before the first member"));
         new ImageProvider("dialogs/conflict", "copystartright").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -33,13 +34,13 @@ public class AddSelectedAtStartAction extends AddFromSelectionAction {
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0);
+        setEnabled(getSelectionTableModel().getRowCount() > 0);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersAtBeginning(filterConfirmedPrimitives(selectionTableModel.getSelection()));
+        	getMemberTableModel().addMembersAtBeginning(filterConfirmedPrimitives(getSelectionTableModel().getSelection()));
         } catch (AddAbortException ex) {
             Logging.trace(ex);
         }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java
index e32ad3c..c8194a9 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddSelectedBeforeSelection.java
@@ -6,9 +6,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
 
@@ -17,6 +14,7 @@ import org.openstreetmap.josm.tools.Logging;
  * @since 9496
  */
 public class AddSelectedBeforeSelection extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code AddSelectedBeforeSelection}.
@@ -24,8 +22,8 @@ public class AddSelectedBeforeSelection extends AddFromSelectionAction {
      * @param selectionTableModel selection table model
      * @param editor relation editor
      */
-    public AddSelectedBeforeSelection(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor editor) {
-        super(null, memberTableModel, null, selectionTableModel, null, null, editor);
+    public AddSelectedBeforeSelection(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Add all objects selected in the current dataset before the first selected member"));
         new ImageProvider("dialogs/conflict", "copybeforecurrentright").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -33,14 +31,15 @@ public class AddSelectedBeforeSelection extends AddFromSelectionAction {
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(selectionTableModel.getRowCount() > 0 && memberTableModel.getSelectionModel().getMinSelectionIndex() >= 0);
+		setEnabled(getSelectionTableModel().getRowCount() > 0
+				&& editorAccess.getMemberTableModel().getSelectionModel().getMinSelectionIndex() >= 0);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
         try {
-            memberTableModel.addMembersBeforeIdx(filterConfirmedPrimitives(selectionTableModel.getSelection()),
-                    memberTableModel.getSelectionModel().getMinSelectionIndex());
+        	editorAccess.getMemberTableModel().addMembersBeforeIdx(filterConfirmedPrimitives(getSelectionTableModel().getSelection()),
+        			editorAccess.getMemberTableModel().getSelectionModel().getMinSelectionIndex());
         } catch (AddAbortException ex) {
             Logging.trace(ex);
         }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java
index 90945ed..68a246b 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java
@@ -4,23 +4,15 @@ package org.openstreetmap.josm.gui.dialogs.relation.actions;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 
-import javax.swing.event.TableModelEvent;
-
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-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.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
  * Apply the current updates.
  * @since 9496
  */
-public class ApplyAction extends SavingAction implements PropertyChangeListener {
+public class ApplyAction extends SavingAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code ApplyAction}.
@@ -30,21 +22,18 @@ public class ApplyAction extends SavingAction implements PropertyChangeListener
      * @param editor relation editor
      * @param tagModel tag editor model
      */
-    public ApplyAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, null);
+    public ApplyAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE, IRelationEditorUpdateOn.TAG_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Apply the current updates"));
         new ImageProvider("save").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Apply"));
-        updateEnabledState();
-        memberTableModel.addTableModelListener(this);
-        tagModel.addPropertyChangeListener(this);
+        updateEnabledState();        
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
         if (applyChanges()) {
-            editor.reloadDataFromRelation();
+        	editorAccess.getEditor().reloadDataFromRelation();
         }
     }
 
@@ -52,14 +41,4 @@ public class ApplyAction extends SavingAction implements PropertyChangeListener
     protected void updateEnabledState() {
         setEnabled(isEditorDirty());
     }
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        updateEnabledState();
-    }
-
-    @Override
-    public void tableChanged(TableModelEvent e) {
-        updateEnabledState();
-    }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java
index 24f8502..9a5a0d7 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java
@@ -12,12 +12,6 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-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.tagging.TagEditorModel;
-import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.InputMapUtils;
@@ -27,6 +21,7 @@ import org.openstreetmap.josm.tools.InputMapUtils;
  * @since 9496
  */
 public class CancelAction extends SavingAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code CancelAction}.
@@ -37,25 +32,24 @@ public class CancelAction extends SavingAction {
      * @param editor relation editor
      * @param tfRole role text field
      */
-    public CancelAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, tfRole);
+    public CancelAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Cancel the updates and close the dialog"));
         new ImageProvider("cancel").getResource().attachImageIcon(this);
         putValue(NAME, tr("Cancel"));
 
-        if (editor instanceof RootPaneContainer) {
-            InputMapUtils.addEscapeAction(((RootPaneContainer) editor).getRootPane(), this);
+        if (getEditor() instanceof RootPaneContainer) {
+            InputMapUtils.addEscapeAction(((RootPaneContainer) getEditor()).getRootPane(), this);
         }
         setEnabled(true);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTable.stopHighlighting();
-        Relation snapshot = editor.getRelationSnapshot();
-        if ((!memberTableModel.hasSameMembersAs(snapshot) || tagModel.isDirty())
-         && !(snapshot == null && tagModel.getTags().isEmpty())) {
+        getMemberTable().stopHighlighting();
+        Relation snapshot = getEditor().getRelationSnapshot();
+        if ((!getMemberTableModel().hasSameMembersAs(snapshot) || getTagModel().isDirty())
+         && !(snapshot == null && getTagModel().getTags().isEmpty())) {
             //give the user a chance to save the changes
             int ret = confirmClosingByCancel();
             if (ret == 0) { //Yes, save the changes
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java
index 8b8ba36..1bc36f4 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java
@@ -7,15 +7,13 @@ import java.util.Collection;
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
 import org.openstreetmap.josm.gui.datatransfer.RelationMemberTransferable;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
  * Copy members.
  * @since 9496
  */
 public class CopyMembersAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code CopyMembersAction}.
@@ -23,13 +21,13 @@ public class CopyMembersAction extends AddFromSelectionAction {
      * @param layer OSM data layer
      * @param editor relation editor
      */
-    public CopyMembersAction(MemberTableModel memberTableModel, OsmDataLayer layer, IRelationEditor editor) {
-        super(null, memberTableModel, null, null, null, layer, editor);
+    public CopyMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        final Collection<RelationMember> members = memberTableModel.getSelectedMembers();
+        final Collection<RelationMember> members = getMemberTableModel().getSelectedMembers();
 
         if (!members.isEmpty()) {
             ClipboardUtils.copy(new RelationMemberTransferable(members));
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java
index 40f761b..5519109 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DeleteCurrentRelationAction.java
@@ -10,8 +10,6 @@ import java.beans.PropertyChangeListener;
 import org.openstreetmap.josm.actions.mapmode.DeleteAction;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -19,14 +17,15 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class DeleteCurrentRelationAction extends AbstractRelationEditorAction implements PropertyChangeListener {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code DeleteCurrentRelationAction}.
      * @param layer OSM data layer
      * @param editor relation editor
      */
-    public DeleteCurrentRelationAction(OsmDataLayer layer, IRelationEditor editor) {
-        super(null, null, null, layer, editor);
+    public DeleteCurrentRelationAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Delete the currently edited relation"));
         new ImageProvider("dialogs", "delete").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Delete"));
@@ -35,15 +34,15 @@ public class DeleteCurrentRelationAction extends AbstractRelationEditorAction im
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        Relation toDelete = editor.getRelation();
+        Relation toDelete = getEditor().getRelation();
         if (toDelete == null)
             return;
-        DeleteAction.deleteRelation(layer, toDelete);
+        DeleteAction.deleteRelation(getLayer(), toDelete);
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(editor.getRelationSnapshot() != null);
+        setEnabled(getEditor().getRelationSnapshot() != null);
     }
 
     @Override
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java
index 6cceee2..d9b69d6 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java
@@ -10,10 +10,6 @@ import java.awt.event.KeyEvent;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-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.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -22,6 +18,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  * @since 9496
  */
 public class DownloadIncompleteMembersAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code DownloadIncompleteMembersAction}.
@@ -31,9 +28,8 @@ public class DownloadIncompleteMembersAction extends AbstractRelationEditorActio
      * @param layer OSM data layer
      * @param editor relation editor
      */
-    public DownloadIncompleteMembersAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey,
-            OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, memberTableModel, actionMapKey, layer, editor);
+    public DownloadIncompleteMembersAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
         Shortcut sc = Shortcut.registerShortcut("relationeditor:downloadincomplete", tr("Relation Editor: Download Members"),
             KeyEvent.VK_HOME, Shortcut.ALT);
         sc.setAccelerator(this);
@@ -48,15 +44,15 @@ public class DownloadIncompleteMembersAction extends AbstractRelationEditorActio
         if (!isEnabled())
             return;
         MainApplication.worker.submit(new DownloadRelationMemberTask(
-                editor.getRelation(),
-                memberTableModel.getIncompleteMemberPrimitives(),
-                layer,
-                (Dialog) editor)
+        		getEditor().getRelation(),
+                getMemberTableModel().getIncompleteMemberPrimitives(),
+                getLayer(),
+                (Dialog) getEditor())
         );
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.hasIncompleteMembers() && canDownload());
+        setEnabled(getMemberTableModel().hasIncompleteMembers() && canDownload());
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java
index 9a30974..327c7f8 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadSelectedIncompleteMembersAction.java
@@ -8,10 +8,6 @@ import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-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.tools.ImageProvider;
 
 /**
@@ -19,6 +15,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class DownloadSelectedIncompleteMembersAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code DownloadSelectedIncompleteMembersAction}.
@@ -28,9 +25,8 @@ public class DownloadSelectedIncompleteMembersAction extends AbstractRelationEdi
      * @param layer OSM data layer
      * @param editor relation editor
      */
-    public DownloadSelectedIncompleteMembersAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey,
-            OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, memberTableModel, actionMapKey, layer, editor);
+    public DownloadSelectedIncompleteMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         putValue(SHORT_DESCRIPTION, tr("Download selected incomplete members"));
         new ImageProvider("dialogs/relation", "downloadincompleteselected").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Download members"));
@@ -42,15 +38,15 @@ public class DownloadSelectedIncompleteMembersAction extends AbstractRelationEdi
         if (!isEnabled())
             return;
         MainApplication.worker.submit(new DownloadRelationMemberTask(
-                editor.getRelation(),
-                memberTableModel.getSelectedIncompleteMemberPrimitives(),
-                layer,
-                (Dialog) editor)
+        		getEditor().getRelation(),
+                getMemberTableModel().getSelectedIncompleteMemberPrimitives(),
+                getLayer(),
+                (Dialog) getEditor())
         );
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.hasIncompleteSelectedMembers() && canDownload());
+        setEnabled(getMemberTableModel().hasIncompleteSelectedMembers() && canDownload());
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java
index ce48ae1..91fcbea 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DuplicateRelationAction.java
@@ -7,10 +7,7 @@ import java.awt.GraphicsEnvironment;
 import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -18,8 +15,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class DuplicateRelationAction extends AbstractRelationEditorAction {
-
-    private final transient TagEditorModel tagEditorModel;
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code DuplicateRelationAction}.
@@ -27,9 +23,8 @@ public class DuplicateRelationAction extends AbstractRelationEditorAction {
      * @param tagEditorModel tag editor model
      * @param layer OSM data layer
      */
-    public DuplicateRelationAction(MemberTableModel memberTableModel, TagEditorModel tagEditorModel, OsmDataLayer layer) {
-        super(null, memberTableModel, null, layer, null);
-        this.tagEditorModel = tagEditorModel;
+    public DuplicateRelationAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Create a copy of this relation and open it in another editor window"));
         // FIXME provide an icon
         new ImageProvider("duplicate").getResource().attachImageIcon(this, true);
@@ -40,10 +35,10 @@ public class DuplicateRelationAction extends AbstractRelationEditorAction {
     @Override
     public void actionPerformed(ActionEvent e) {
         Relation copy = new Relation();
-        tagEditorModel.applyToPrimitive(copy);
-        memberTableModel.applyToRelation(copy);
+        getTagModel().applyToPrimitive(copy);
+        editorAccess.getMemberTableModel().applyToRelation(copy);
         if (!GraphicsEnvironment.isHeadless()) {
-            RelationEditor.getEditor(layer, copy, memberTableModel.getSelectedMembers()).setVisible(true);
+            RelationEditor.getEditor(getLayer(), copy, editorAccess.getMemberTableModel().getSelectedMembers()).setVisible(true);
         }
     }
 
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java
index 44f4a19..26c95ec 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/EditAction.java
@@ -10,10 +10,7 @@ import java.util.HashSet;
 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.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -21,6 +18,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class EditAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code EditAction}.
@@ -28,8 +26,8 @@ public class EditAction extends AbstractRelationEditorAction {
      * @param memberTableModel member table model
      * @param layer layer
      */
-    public EditAction(MemberTable memberTable, MemberTableModel memberTableModel, OsmDataLayer layer) {
-        super(memberTable, memberTableModel, null, layer, null);
+    public EditAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         putValue(SHORT_DESCRIPTION, tr("Edit the relation the currently selected relation member refers to"));
         new ImageProvider("dialogs", "edit").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -37,13 +35,14 @@ public class EditAction extends AbstractRelationEditorAction {
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTable.getSelectedRowCount() == 1
-                && memberTableModel.isEditableRelation(memberTable.getSelectedRow()));
+        setEnabled(editorAccess.getMemberTable().getSelectedRowCount() == 1
+				&& editorAccess.getMemberTableModel()
+						.isEditableRelation(editorAccess.getMemberTable().getSelectedRow()));
     }
 
     protected Collection<RelationMember> getMembersForCurrentSelection(Relation r) {
         Collection<RelationMember> members = new HashSet<>();
-        Collection<OsmPrimitive> selection = layer.data.getSelected();
+        Collection<OsmPrimitive> selection = getLayer().data.getSelected();
         for (RelationMember member: r.getMembers()) {
             if (selection.contains(member.getMember())) {
                 members.add(member);
@@ -56,16 +55,16 @@ public class EditAction extends AbstractRelationEditorAction {
     public void actionPerformed(ActionEvent e) {
         if (!isEnabled())
             return;
-        int idx = memberTable.getSelectedRow();
+        int idx = editorAccess.getMemberTable().getSelectedRow();
         if (idx < 0)
             return;
-        OsmPrimitive primitive = memberTableModel.getReferredPrimitive(idx);
+        OsmPrimitive primitive = editorAccess.getMemberTableModel().getReferredPrimitive(idx);
         if (!(primitive instanceof Relation))
             return;
         Relation r = (Relation) primitive;
         if (r.isIncomplete())
             return;
 
-        RelationEditor.getEditor(layer, r, getMembersForCurrentSelection(r)).setVisible(true);
+        RelationEditor.getEditor(getLayer(), r, getMembersForCurrentSelection(r)).setVisible(true);
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java
new file mode 100644
index 0000000..e1c507a
--- /dev/null
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java
@@ -0,0 +1,63 @@
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import javax.swing.Action;
+
+import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
+import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
+import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTable;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
+import org.openstreetmap.josm.gui.tagging.TagEditorModel;
+import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
+
+/**
+ * This interface provides access to the relation editor for actions.
+ * <p>
+ * 
+ * @author Michael Zangl
+ * @since xxx
+ */
+public interface IRelationEditorActionAccess {
+
+	/**
+	 * Adds a keyboard action to the member table.
+	 * @param actionMapKey The key to use
+	 * @param action The action to map for that key.
+	 */
+	default void addMemberTableAction(String actionMapKey, Action action) {
+		getMemberTable().getActionMap().put(actionMapKey, action);
+	}
+
+	/**
+	 * Get the member table that is used by the dialog.
+	 * @return The member table
+	 */
+	MemberTable getMemberTable();
+	
+	/**
+	 * Get the model the member table is using.
+	 * @return That model
+	 */
+	MemberTableModel getMemberTableModel();
+	
+	/**
+	 * Get the table that displays the current user selection
+	 * @return That table
+	 */
+	SelectionTable getSelectionTable();
+	
+	/**
+	 * Get the model that the selection table is based on.
+	 * @return The model
+	 */
+    SelectionTableModel getSelectionTableModel();
+    
+    IRelationEditor getEditor();
+    TagEditorModel getTagModel();
+    
+    /**
+     * Get the text field that is used to edit the role.
+     * @return The role text field.
+     */
+    AutoCompletingTextField getTextFieldRole();
+}
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionGroup.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionGroup.java
new file mode 100644
index 0000000..3dc443d
--- /dev/null
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionGroup.java
@@ -0,0 +1,52 @@
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import java.util.Comparator;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JToolBar;
+
+import org.openstreetmap.josm.actions.ExpertToggleAction;
+
+/**
+ * An action group for the relation editor, to be used in one of the tool bars.
+ * 
+ * @author Michael Zangl
+ * @since xxx
+ */
+public interface IRelationEditorActionGroup {
+
+	/**
+	 * Get the position at which the action group should be added.
+	 * 
+	 * @return The order index, default is to add at the end.
+	 */
+	default int order() {
+		return 100;
+	}
+
+	/**
+	 * Get the actions in this action group.
+	 * 
+	 * @param editorAccess
+	 *            Methods to access the relation editor.
+	 * @return The actions
+	 */
+	List<AbstractRelationEditorAction> getActions(IRelationEditorActionAccess editorAccess);
+
+	static void fillToolbar(JToolBar toolbar, List<IRelationEditorActionGroup> groups,
+			IRelationEditorActionAccess editorAccess) {
+		groups.stream().sorted(Comparator.comparingInt(IRelationEditorActionGroup::order)).forEach(group -> {
+			if (toolbar.getComponentCount() > 0) {
+				toolbar.addSeparator();
+			}
+
+			for (AbstractRelationEditorAction action : group.getActions(editorAccess)) {
+				JButton button = toolbar.add(action);
+				if (action.isExpertOnly()) {
+					ExpertToggleAction.addVisibilitySwitcher(button);
+				}
+			}
+		});
+	}
+}
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorUpdateOn.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorUpdateOn.java
new file mode 100644
index 0000000..78e8e66
--- /dev/null
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorUpdateOn.java
@@ -0,0 +1,30 @@
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+/**
+ * This interface can be used to register the event listeners for a
+ * {@link AbstractRelationEditorAction}.
+ * <p>
+ * It holds common constants that are often used.
+ * 
+ * @author Michael Zangl
+ * @since xxx
+ */
+@FunctionalInterface
+public interface IRelationEditorUpdateOn {
+	/**
+	 * Update when the member table contents change
+	 */
+	IRelationEditorUpdateOn MEMBER_TABLE_CHANGE = (editor, action) -> editor.getMemberTableModel()
+			.addTableModelListener(action);
+	/**
+	 * Update upon a member table selection change
+	 */
+	IRelationEditorUpdateOn MEMBER_TABLE_SELECTION = (editor, action) -> editor.getMemberTable().getSelectionModel()
+			.addListSelectionListener(action);
+
+	IRelationEditorUpdateOn TAG_CHANGE = (editor, action) -> editor.getTagModel().addPropertyChangeListener(action);
+	IRelationEditorUpdateOn SELECTION_TABLE_CHANGE = (editor, action) -> editor.getSelectionTableModel()
+			.addTableModelListener(action);
+
+	void register(IRelationEditorActionAccess editor, AbstractRelationEditorAction action);
+}
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java
index ec691e6..69c84c3 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java
@@ -7,8 +7,6 @@ import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -17,6 +15,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  * @since 9496
  */
 public class MoveDownAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code MoveDownAction}.
@@ -24,8 +23,8 @@ public class MoveDownAction extends AbstractRelationEditorAction {
      * @param memberTableModel member table model
      * @param actionMapKey action map key
      */
-    public MoveDownAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        super(memberTable, memberTableModel, actionMapKey);
+    public MoveDownAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "movedown").getResource().attachImageIcon(this, true);
         Shortcut sc = Shortcut.registerShortcut("relationeditor:movedown", tr("Relation Editor: Move Down"), KeyEvent.VK_DOWN, Shortcut.ALT);
         sc.setAccelerator(this);
@@ -35,11 +34,11 @@ public class MoveDownAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.moveDown(memberTable.getSelectedRows());
+    	editorAccess.getMemberTableModel().moveDown(editorAccess.getMemberTable().getSelectedRows());
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.canMoveDown(memberTable.getSelectedRows()));
+        setEnabled(editorAccess.getMemberTableModel().canMoveDown(editorAccess.getMemberTable().getSelectedRows()));
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java
index aceb7f5..0f84f98 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java
@@ -7,8 +7,6 @@ import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -17,6 +15,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  * @since 9496
  */
 public class MoveUpAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code MoveUpAction}.
@@ -24,8 +23,8 @@ public class MoveUpAction extends AbstractRelationEditorAction {
      * @param memberTableModel member table model
      * @param actionMapKey key in table action map
      */
-    public MoveUpAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        super(memberTable, memberTableModel, actionMapKey);
+    public MoveUpAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "moveup").getResource().attachImageIcon(this, true);
         Shortcut sc = Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Up"), KeyEvent.VK_UP, Shortcut.ALT);
         sc.setAccelerator(this);
@@ -35,11 +34,11 @@ public class MoveUpAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.moveUp(memberTable.getSelectedRows());
+    	editorAccess.getMemberTableModel().moveUp(editorAccess.getMemberTable().getSelectedRows());
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.canMoveUp(memberTable.getSelectedRows()));
+        setEnabled(editorAccess.getMemberTableModel().canMoveUp(editorAccess.getMemberTable().getSelectedRows()));
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java
index 6317915..f821791 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/OKAction.java
@@ -5,12 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-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.tagging.TagEditorModel;
-import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -18,6 +12,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * Apply the updates and close the dialog.
  */
 public class OKAction extends SavingAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code OKAction}.
@@ -28,9 +23,8 @@ public class OKAction extends SavingAction {
      * @param editor relation editor
      * @param tfRole role text field
      */
-    public OKAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, tfRole);
+    public OKAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(SHORT_DESCRIPTION, tr("Apply the updates and close the dialog"));
         new ImageProvider("ok").getResource().attachImageIcon(this);
         putValue(NAME, tr("OK"));
@@ -40,7 +34,7 @@ public class OKAction extends SavingAction {
     @Override
     public void actionPerformed(ActionEvent e) {
         Config.getPref().put("relation.editor.generic.lastrole", tfRole.getText());
-        memberTable.stopHighlighting();
+        editorAccess.getMemberTable().stopHighlighting();
         if (!applyChanges())
             return;
         hideEditor();
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java
index dd0d969..7c92ad4 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java
@@ -9,10 +9,7 @@ import java.util.Optional;
 import javax.swing.TransferHandler.TransferSupport;
 
 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
 import org.openstreetmap.josm.gui.dialogs.relation.MemberTransferHandler;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.Logging;
 
 /**
@@ -20,6 +17,7 @@ import org.openstreetmap.josm.tools.Logging;
  * @since 9496
  */
 public class PasteMembersAction extends AddFromSelectionAction implements FlavorListener {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code PasteMembersAction}.
@@ -27,8 +25,8 @@ public class PasteMembersAction extends AddFromSelectionAction implements Flavor
      * @param layer OSM data layer
      * @param editor relation editor
      */
-    public PasteMembersAction(MemberTable memberTable, OsmDataLayer layer, IRelationEditor editor) {
-        super(memberTable, null, null, null, null, layer, editor);
+    public PasteMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         updateEnabledState();
     }
 
@@ -42,7 +40,7 @@ public class PasteMembersAction extends AddFromSelectionAction implements Flavor
     }
 
     private TransferSupport getSupport() {
-        return new TransferSupport(memberTable, Optional.ofNullable(ClipboardUtils.getClipboardContent())
+        return new TransferSupport(editorAccess.getMemberTable(), Optional.ofNullable(ClipboardUtils.getClipboardContent())
                 .orElseThrow(() -> new IllegalStateException("Failed to retrieve clipboard content")));
     }
 
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
index d43e736..3b286a3 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
@@ -15,11 +15,6 @@ import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-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.tagging.TagEditorModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -28,6 +23,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  * @since 9657
  */
 public class RefreshAction extends SavingAction implements CommandQueueListener {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code RefreshAction}.
@@ -37,18 +33,17 @@ public class RefreshAction extends SavingAction implements CommandQueueListener
      * @param editor relation editor
      * @param tagModel tag editor model
      */
-    public RefreshAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor) {
-        super(memberTable, memberTableModel, tagModel, layer, editor, null);
+    public RefreshAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         // CHECKSTYLE.OFF: LineLength
         Shortcut sc = Shortcut.registerShortcut("relationeditor:refresh", tr("Relation Editor: Refresh"), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE);
         // CHECKSTYLE.ON: LineLength
         putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Refresh relation from data layer"), sc));
         new ImageProvider("dialogs/refresh").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Refresh"));
-        if (editor instanceof JComponent) {
-            ((JComponent) editor).getRootPane().getActionMap().put("refresh", this);
-            ((JComponent) editor).getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), "refresh");
+        if (editorAccess.getEditor() instanceof JComponent) {
+            ((JComponent) editorAccess.getEditor()).getRootPane().getActionMap().put("refresh", this);
+            ((JComponent) editorAccess.getEditor()).getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), "refresh");
         }
         MainApplication.undoRedo.addCommandQueueListener(this);
         updateEnabledState();
@@ -56,7 +51,7 @@ public class RefreshAction extends SavingAction implements CommandQueueListener
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        Relation relation = editor.getRelation();
+        Relation relation = editorAccess.getEditor().getRelation();
         if (relation == null)
             return;
         if (relation.isDeleted()) {
@@ -67,13 +62,13 @@ public class RefreshAction extends SavingAction implements CommandQueueListener
         }
         if (isEditorDirty() && confirmDiscardDirtyData() != 0)
             return;
-        editor.reloadDataFromRelation();
+        editorAccess.getEditor().reloadDataFromRelation();
     }
 
     @Override
     public void updateEnabledState() {
-        Relation relation = editor.getRelation();
-        Relation snapshot = editor.getRelationSnapshot();
+        Relation relation = editorAccess.getEditor().getRelation();
+        Relation snapshot = editorAccess.getEditor().getRelationSnapshot();
         setEnabled(snapshot != null && (
             !relation.hasEqualTechnicalAttributes(snapshot) ||
             !relation.hasEqualSemanticAttributes(snapshot)
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java
index fc09cf2..ba0b5db 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java
@@ -7,8 +7,6 @@ import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -17,6 +15,7 @@ import org.openstreetmap.josm.tools.Shortcut;
  * @since 9496
  */
 public class RemoveAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code RemoveAction}.
@@ -24,8 +23,8 @@ public class RemoveAction extends AbstractRelationEditorAction {
      * @param memberTableModel member table model
      * @param actionMapKey action map key
      */
-    public RemoveAction(MemberTable memberTable, MemberTableModel memberTableModel, String actionMapKey) {
-        super(memberTable, memberTableModel, actionMapKey);
+    public RemoveAction(IRelationEditorActionAccess editorAccess, String actionMapKey) {
+        super(editorAccess, actionMapKey, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "delete").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Remove"));
         Shortcut sc = Shortcut.registerShortcut("relationeditor:remove", tr("Relation Editor: Remove"), KeyEvent.VK_DELETE, Shortcut.ALT);
@@ -36,11 +35,11 @@ public class RemoveAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.remove(memberTable.getSelectedRows());
+        editorAccess.getMemberTableModel().remove(editorAccess.getMemberTable().getSelectedRows());
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.canRemove(memberTable.getSelectedRows()));
+        setEnabled(editorAccess.getMemberTableModel().canRemove(editorAccess.getMemberTable().getSelectedRows()));
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java
index f92c586..013a7aa 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveSelectedAction.java
@@ -6,9 +6,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -16,6 +13,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class RemoveSelectedAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code RemoveSelectedAction}.
@@ -23,8 +21,8 @@ public class RemoveSelectedAction extends AddFromSelectionAction {
      * @param selectionTableModel selection table model
      * @param layer OSM data layer
      */
-    public RemoveSelectedAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, OsmDataLayer layer) {
-        super(null, memberTableModel, null, selectionTableModel, null, layer, null);
+    public RemoveSelectedAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Remove all members referring to one of the selected objects"));
         new ImageProvider("dialogs/relation", "deletemembers").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -32,17 +30,17 @@ public class RemoveSelectedAction extends AddFromSelectionAction {
 
     @Override
     protected void updateEnabledState() {
-        DataSet ds = layer.data;
+        DataSet ds = getLayer().data;
         if (ds == null || ds.selectionEmpty()) {
             setEnabled(false);
             return;
         }
         // only enable the action if we have members referring to the selected primitives
-        setEnabled(memberTableModel.hasMembersReferringTo(ds.getSelected()));
+        setEnabled(editorAccess.getMemberTableModel().hasMembersReferringTo(ds.getSelected()));
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.removeMembersReferringTo(selectionTableModel.getSelection());
+    	editorAccess.getMemberTableModel().removeMembersReferringTo(getSelectionTableModel().getSelection());
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java
index 9fa0534..2c8f01e 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/ReverseAction.java
@@ -5,8 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -14,14 +12,15 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class ReverseAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code ReverseAction}.
-     * @param memberTable member table
-     * @param memberTableModel member table model
+     * @param editorAccess
      */
-    public ReverseAction(MemberTable memberTable, MemberTableModel memberTableModel) {
-        super(memberTable, memberTableModel, null);
+    public ReverseAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
+
         putValue(SHORT_DESCRIPTION, tr("Reverse the order of the relation members"));
         new ImageProvider("dialogs/relation", "reverse").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Reverse"));
@@ -30,11 +29,11 @@ public class ReverseAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.reverse();
+        editorAccess.getMemberTableModel().reverse();
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.getRowCount() > 0);
+        setEnabled(editorAccess.getMemberTableModel().getRowCount() > 0);
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java
index 6d333c0..ca2d2a3 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java
@@ -21,12 +21,8 @@ import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationDialogManager;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -37,15 +33,13 @@ import org.openstreetmap.josm.tools.Utils;
  * @since 9496
  */
 abstract class SavingAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
-    protected final TagEditorModel tagModel;
     protected final AutoCompletingTextField tfRole;
 
-    protected SavingAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
-            IRelationEditor editor, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, null, layer, editor);
-        this.tagModel = tagModel;
-        this.tfRole = tfRole;
+    protected SavingAction(IRelationEditorActionAccess editorAccess, IRelationEditorUpdateOn... updateOn) {
+        super(editorAccess, updateOn);
+        this.tfRole = editorAccess.getTextFieldRole();
     }
 
     /**
@@ -55,7 +49,7 @@ abstract class SavingAction extends AbstractRelationEditorAction {
     protected void applyNewRelation(TagEditorModel tagEditorModel) {
         final Relation newRelation = new Relation();
         tagEditorModel.applyToPrimitive(newRelation);
-        memberTableModel.applyToRelation(newRelation);
+        getMemberTableModel().applyToRelation(newRelation);
         List<RelationMember> newMembers = new ArrayList<>();
         for (RelationMember rm: newRelation.getMembers()) {
             if (!rm.getMember().isDeleted()) {
@@ -72,14 +66,14 @@ abstract class SavingAction extends AbstractRelationEditorAction {
         // tags, don't add an empty relation
         if (newRelation.getMembersCount() == 0 && !newRelation.hasKeys())
             return;
-        MainApplication.undoRedo.add(new AddCommand(layer.getDataSet(), newRelation));
+        MainApplication.undoRedo.add(new AddCommand(getLayer().getDataSet(), newRelation));
 
         // make sure everybody is notified about the changes
         //
-        editor.setRelation(newRelation);
-        if (editor instanceof RelationEditor) {
+        getEditor().setRelation(newRelation);
+        if (getEditor() instanceof RelationEditor) {
             RelationDialogManager.getRelationDialogManager().updateContext(
-                    layer, editor.getRelation(), (RelationEditor) editor);
+                    getLayer(), getEditor().getRelation(), (RelationEditor) getEditor());
         }
         // Relation list gets update in EDT so selecting my be postponed to following EDT run
         SwingUtilities.invokeLater(() -> MainApplication.getMap().relationListDialog.selectRelation(newRelation));
@@ -90,11 +84,11 @@ abstract class SavingAction extends AbstractRelationEditorAction {
      * @param tagEditorModel tag editor model
      */
     protected void applyExistingConflictingRelation(TagEditorModel tagEditorModel) {
-        Relation editedRelation = new Relation(editor.getRelation());
+        Relation editedRelation = new Relation(editorAccess.getEditor().getRelation());
         tagEditorModel.applyToPrimitive(editedRelation);
-        memberTableModel.applyToRelation(editedRelation);
-        Conflict<Relation> conflict = new Conflict<>(editor.getRelation(), editedRelation);
-        MainApplication.undoRedo.add(new ConflictAddCommand(layer.getDataSet(), conflict));
+        editorAccess.getMemberTableModel().applyToRelation(editedRelation);
+        Conflict<Relation> conflict = new Conflict<>(editorAccess.getEditor().getRelation(), editedRelation);
+        MainApplication.undoRedo.add(new ConflictAddCommand(getLayer().getDataSet(), conflict));
     }
 
     /**
@@ -102,10 +96,10 @@ abstract class SavingAction extends AbstractRelationEditorAction {
      * @param tagEditorModel tag editor model
      */
     protected void applyExistingNonConflictingRelation(TagEditorModel tagEditorModel) {
-        Relation originRelation = editor.getRelation();
+        Relation originRelation = editorAccess.getEditor().getRelation();
         Relation editedRelation = new Relation(originRelation);
         tagEditorModel.applyToPrimitive(editedRelation);
-        memberTableModel.applyToRelation(editedRelation);
+        getMemberTableModel().applyToRelation(editedRelation);
         if (!editedRelation.hasEqualSemanticAttributes(originRelation, false)) {
             MainApplication.undoRedo.add(new ChangeCommand(originRelation, editedRelation));
         }
@@ -152,8 +146,8 @@ abstract class SavingAction extends AbstractRelationEditorAction {
                 tr("<html>Layer ''{0}'' already has a conflict for object<br>"
                         + "''{1}''.<br>"
                         + "Please resolve this conflict first, then try again.</html>",
-                        Utils.escapeReservedCharactersHTML(layer.getName()),
-                        Utils.escapeReservedCharactersHTML(editor.getRelation().getDisplayName(DefaultNameFormatter.getInstance()))
+                        Utils.escapeReservedCharactersHTML(getLayer().getName()),
+                        Utils.escapeReservedCharactersHTML(getEditor().getRelation().getDisplayName(DefaultNameFormatter.getInstance()))
                 ),
                 tr("Double conflict"),
                 JOptionPane.WARNING_MESSAGE
@@ -166,35 +160,35 @@ abstract class SavingAction extends AbstractRelationEditorAction {
     }
 
     protected boolean applyChanges() {
-        if (editor.getRelation() == null) {
-            applyNewRelation(tagModel);
+        if (editorAccess.getEditor().getRelation() == null) {
+            applyNewRelation(getTagModel());
         } else if (isEditorDirty()) {
-            if (editor.isDirtyRelation()) {
+            if (editorAccess.getEditor().isDirtyRelation()) {
                 if (confirmClosingBecauseOfDirtyState()) {
-                    if (layer.getConflicts().hasConflictForMy(editor.getRelation())) {
+                    if (getLayer().getConflicts().hasConflictForMy(editorAccess.getEditor().getRelation())) {
                         warnDoubleConflict();
                         return false;
                     }
-                    applyExistingConflictingRelation(tagModel);
+                    applyExistingConflictingRelation(getTagModel());
                     hideEditor();
                 } else
                     return false;
             } else {
-                applyExistingNonConflictingRelation(tagModel);
+                applyExistingNonConflictingRelation(getTagModel());
             }
         }
-        editor.setRelation(editor.getRelation());
+        editorAccess.getEditor().setRelation(editorAccess.getEditor().getRelation());
         return true;
     }
 
     protected void hideEditor() {
-        if (editor instanceof Component) {
-            ((Component) editor).setVisible(false);
+        if (editorAccess.getEditor() instanceof Component) {
+            ((Component) editorAccess.getEditor()).setVisible(false);
         }
     }
 
     protected boolean isEditorDirty() {
-        Relation snapshot = editor.getRelationSnapshot();
-        return (snapshot != null && !memberTableModel.hasSameMembersAs(snapshot)) || tagModel.isDirty();
+        Relation snapshot = editorAccess.getEditor().getRelationSnapshot();
+        return (snapshot != null && !getMemberTableModel().hasSameMembersAs(snapshot)) || getTagModel().isDirty();
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java
index 14c8d25..6bb04ef 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectAction.java
@@ -6,8 +6,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import java.awt.event.ActionEvent;
 
 import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -15,14 +13,15 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 12933
  */
 public class SelectAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code SelectAction}.
      * @param layer OSM data layer
      * @param editor relation editor
      */
-    public SelectAction(OsmDataLayer layer, IRelationEditor editor) {
-        super(null, null, null, layer, editor);
+    public SelectAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
         putValue(NAME, tr("Select"));
         putValue(SHORT_DESCRIPTION, tr("Select the currently edited relation"));
         new ImageProvider("dialogs", "select").getResource().attachImageIcon(this, true);
@@ -31,14 +30,14 @@ public class SelectAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        Relation toSelect = editor.getRelation();
+        Relation toSelect = editorAccess.getEditor().getRelation();
         if (toSelect == null)
             return;
-        layer.data.setSelected(toSelect);
+        getLayer().data.setSelected(toSelect);
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(editor.getRelationSnapshot() != null);
+        setEnabled(editorAccess.getEditor().getRelationSnapshot() != null);
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java
index 6a5fe0f..fc998a2 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectPrimitivesForSelectedMembersAction.java
@@ -5,9 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
 
-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.tools.ImageProvider;
 
 /**
@@ -16,6 +13,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class SelectPrimitivesForSelectedMembersAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Select objects for selected relation members.
@@ -23,8 +21,8 @@ public class SelectPrimitivesForSelectedMembersAction extends AbstractRelationEd
      * @param memberTableModel member table model
      * @param layer layer
      */
-    public SelectPrimitivesForSelectedMembersAction(MemberTable memberTable, MemberTableModel memberTableModel, OsmDataLayer layer) {
-        super(memberTable, memberTableModel, null, layer, null);
+    public SelectPrimitivesForSelectedMembersAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         putValue(SHORT_DESCRIPTION, tr("Select objects for selected relation members"));
         new ImageProvider("dialogs/relation", "selectprimitives").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -32,11 +30,11 @@ public class SelectPrimitivesForSelectedMembersAction extends AbstractRelationEd
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTable.getSelectedRowCount() > 0);
+        setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0);
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        layer.data.setSelected(memberTableModel.getSelectedChildPrimitives());
+        getLayer().data.setSelected(editorAccess.getMemberTableModel().getSelectedChildPrimitives());
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java
index 642c0be..0f905ba 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SelectedMembersForSelectionAction.java
@@ -5,9 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
-import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -15,6 +12,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class SelectedMembersForSelectionAction extends AddFromSelectionAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code SelectedMembersForSelectionAction}.
@@ -22,8 +20,8 @@ public class SelectedMembersForSelectionAction extends AddFromSelectionAction {
      * @param selectionTableModel selection table model
      * @param layer OSM data layer
      */
-    public SelectedMembersForSelectionAction(MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, OsmDataLayer layer) {
-        super(null, memberTableModel, null, selectionTableModel, null, layer, null);
+    public SelectedMembersForSelectionAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
         putValue(SHORT_DESCRIPTION, tr("Select relation members which refer to objects in the current selection"));
         new ImageProvider("dialogs/relation", "selectmembers").getResource().attachImageIcon(this, true);
         updateEnabledState();
@@ -31,12 +29,12 @@ public class SelectedMembersForSelectionAction extends AddFromSelectionAction {
 
     @Override
     protected void updateEnabledState() {
-        boolean enabled = selectionTableModel.getRowCount() > 0
-        && !memberTableModel.getChildPrimitives(layer.data.getSelected()).isEmpty();
+        boolean enabled = getSelectionTableModel().getRowCount() > 0
+        && !editorAccess.getMemberTableModel().getChildPrimitives(getLayer().data.getSelected()).isEmpty();
 
         if (enabled) {
             putValue(SHORT_DESCRIPTION, tr("Select relation members which refer to {0} objects in the current selection",
-                    memberTableModel.getChildPrimitives(layer.data.getSelected()).size()));
+            		editorAccess.getMemberTableModel().getChildPrimitives(getLayer().data.getSelected()).size()));
         } else {
             putValue(SHORT_DESCRIPTION, tr("Select relation members which refer to objects in the current selection"));
         }
@@ -45,6 +43,6 @@ public class SelectedMembersForSelectionAction extends AddFromSelectionAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.selectMembersReferringTo(layer.data.getSelected());
+    	editorAccess.getMemberTableModel().selectMembersReferringTo(getLayer().data.getSelected());
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java
index 0d42ba7..07a0df2 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SetRoleAction.java
@@ -12,8 +12,6 @@ import javax.swing.event.DocumentListener;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -22,6 +20,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class SetRoleAction extends AbstractRelationEditorAction implements DocumentListener {
+	private static final long serialVersionUID = 1L;
 
     private final transient AutoCompletingTextField tfRole;
 
@@ -31,9 +30,9 @@ public class SetRoleAction extends AbstractRelationEditorAction implements Docum
      * @param memberTableModel member table model
      * @param tfRole role text field
      */
-    public SetRoleAction(MemberTable memberTable, MemberTableModel memberTableModel, AutoCompletingTextField tfRole) {
-        super(memberTable, memberTableModel, null);
-        this.tfRole = tfRole;
+    public SetRoleAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess);
+        this.tfRole = editorAccess.getTextFieldRole();
         putValue(SHORT_DESCRIPTION, tr("Sets a role for the selected members"));
         new ImageProvider("apply").getResource().attachImageIcon(this);
         putValue(NAME, tr("Apply Role"));
@@ -42,7 +41,7 @@ public class SetRoleAction extends AbstractRelationEditorAction implements Docum
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTable.getSelectedRowCount() > 0);
+        setEnabled(editorAccess.getMemberTable().getSelectedRowCount() > 0);
     }
 
     protected boolean isEmptyRole() {
@@ -82,10 +81,10 @@ public class SetRoleAction extends AbstractRelationEditorAction implements Docum
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        if (isEmptyRole() && !confirmSettingEmptyRole(memberTable.getSelectedRowCount())) {
+        if (isEmptyRole() && !confirmSettingEmptyRole(editorAccess.getMemberTable().getSelectedRowCount())) {
             return;
         }
-        memberTableModel.updateRole(memberTable.getSelectedRows(), tfRole.getText());
+        editorAccess.getMemberTableModel().updateRole(editorAccess.getMemberTable().getSelectedRows(), tfRole.getText());
     }
 
     @Override
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java
index 49cf2bb..c70ce9f 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java
@@ -7,8 +7,6 @@ import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -17,14 +15,15 @@ import org.openstreetmap.josm.tools.Shortcut;
  * @since 9496
  */
 public class SortAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code SortAction}.
      * @param memberTable member table
      * @param memberTableModel member table model
      */
-    public SortAction(MemberTable memberTable, MemberTableModel memberTableModel) {
-        super(memberTable, memberTableModel, null);
+    public SortAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE);
         new ImageProvider("dialogs", "sort").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Sort"));
         Shortcut sc = Shortcut.registerShortcut("relationeditor:sort", tr("Relation Editor: Sort"), KeyEvent.VK_END, Shortcut.ALT);
@@ -35,11 +34,11 @@ public class SortAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.sort();
+    	editorAccess.getMemberTableModel().sort();
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.getRowCount() > 0);
+        setEnabled(editorAccess.getMemberTableModel().getRowCount() > 0);
     }
 }
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java
index b7ea8d4..35812eb 100644
--- a/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java
+++ b/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortBelowAction.java
@@ -5,8 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
 
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
-import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
 import org.openstreetmap.josm.tools.ImageProvider;
 
 /**
@@ -14,14 +12,15 @@ import org.openstreetmap.josm.tools.ImageProvider;
  * @since 9496
  */
 public class SortBelowAction extends AbstractRelationEditorAction {
+	private static final long serialVersionUID = 1L;
 
     /**
      * Constructs a new {@code SortBelowAction}.
      * @param memberTable member table
      * @param memberTableModel member table model
      */
-    public SortBelowAction(MemberTable memberTable, MemberTableModel memberTableModel) {
-        super(memberTable, memberTableModel, null);
+    public SortBelowAction(IRelationEditorActionAccess editorAccess) {
+        super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_CHANGE, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION);
         new ImageProvider("dialogs", "sort_below").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Sort below"));
         putValue(SHORT_DESCRIPTION, tr("Sort the selected relation members and all members below"));
@@ -30,11 +29,16 @@ public class SortBelowAction extends AbstractRelationEditorAction {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        memberTableModel.sortBelow();
+    	editorAccess.getMemberTableModel().sortBelow();
     }
 
     @Override
     protected void updateEnabledState() {
-        setEnabled(memberTableModel.getRowCount() > 0 && !memberTableModel.getSelectionModel().isSelectionEmpty());
+        setEnabled(editorAccess.getMemberTableModel().getRowCount() > 0 && !editorAccess.getMemberTableModel().getSelectionModel().isSelectionEmpty());
+    }
+    
+    @Override
+    public boolean isExpertOnly() {
+    	return true;
     }
 }
diff --git a/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java b/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java
index 5ad6461..26fbbfd 100644
--- a/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java
+++ b/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java
@@ -117,34 +117,14 @@ public class GenericRelationEditorTest {
         SelectionTableModel selectionTableModel = new SelectionTableModel(layer);
         SelectionTable selectionTable = new SelectionTable(selectionTableModel, memberTableModel);
 
-        LeftButtonToolbar leftButtonToolbar = new LeftButtonToolbar(memberTable, memberTableModel, re);
-        assertNotNull(leftButtonToolbar.sortBelowButton);
-
         AutoCompletingTextField tfRole = GenericRelationEditor.buildRoleTextField(re);
         assertNotNull(tfRole);
 
         TagEditorPanel tagEditorPanel = new TagEditorPanel(relation, null);
 
         JPanel top = GenericRelationEditor.buildTagEditorPanel(tagEditorPanel);
-        JPanel bottom = GenericRelationEditor.buildMemberEditorPanel(
-                memberTable, memberTableModel, selectionTable, selectionTableModel, re, leftButtonToolbar, tfRole);
         assertNotNull(top);
-        assertNotNull(bottom);
-        assertNotNull(GenericRelationEditor.buildSplitPane(top, bottom, re));
-
         TagEditorModel tagModel = tagEditorPanel.getModel();
 
-        assertNotNull(GenericRelationEditor.buildOkCancelButtonPanel(
-                new OKAction(memberTable, memberTableModel, tagModel, layer, re, tfRole),
-                new CancelAction(memberTable, memberTableModel, tagModel, layer, re, tfRole)));
-        assertNotNull(GenericRelationEditor.buildSelectionControlButtonToolbar(memberTable, memberTableModel, selectionTableModel, re));
-        assertNotNull(GenericRelationEditor.buildSelectionTablePanel(selectionTable));
-
-        assertNotNull(GenericRelationEditor.buildToolBar(
-                new RefreshAction(memberTable, memberTableModel, tagModel, layer, re),
-                new ApplyAction(memberTable, memberTableModel, tagModel, layer, re),
-                new SelectAction(layer, re),
-                new DuplicateRelationAction(memberTableModel, tagModel, layer),
-                new DeleteCurrentRelationAction(layer, re)));
     }
 }
