Index: /trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java	(revision 6563)
+++ /trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java	(revision 6564)
@@ -10,4 +10,5 @@
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -33,5 +34,7 @@
 import org.openstreetmap.josm.gui.Notification;
 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
+import org.openstreetmap.josm.tools.Pair;
 import org.openstreetmap.josm.tools.Shortcut;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -56,5 +59,5 @@
      */
     public CreateMultipolygonAction() {
-        super(tr("Create multipolygon"), "multipoly_create", tr("Create multipolygon."),
+        super(tr("Create multipolygon"), "multipoly_create", tr("Create multipolygon"),
             Shortcut.registerShortcut("tools:multipoly", tr("Tool: {0}", tr("Create multipolygon")),
             KeyEvent.VK_A, Shortcut.ALT_CTRL), true);
@@ -76,5 +79,6 @@
         }
 
-        Collection<Way> selectedWays = Main.main.getCurrentDataSet().getSelectedWays();
+        final Collection<Way> selectedWays = Main.main.getCurrentDataSet().getSelectedWays();
+        final Collection<Relation> selectedRelations = Main.main.getCurrentDataSet().getSelectedRelations();
 
         if (selectedWays.size() < 1) {
@@ -89,49 +93,85 @@
         }
 
-        MultipolygonCreate polygon = this.analyzeWays(selectedWays);
-
-        if (polygon == null)
-            return;                   //could not make multipolygon.
-
-        final Relation relation = this.createRelation(polygon);
-
-        if (Main.pref.getBoolean("multipoly.show-relation-editor", false)) {
-            //Open relation edit window, if set up in preferences
-            RelationEditor editor = RelationEditor.getEditor(Main.main.getEditLayer(), relation, null);
-
-            editor.setModal(true);
-            editor.setVisible(true);
-
-            //TODO: cannot get the resulting relation from RelationEditor :(.
-            /*
-            if (relationCountBefore < relationCountAfter) {
-                //relation saved, clean up the tags
-                List<Command> list = this.removeTagsFromInnerWays(relation);
-                if (list.size() > 0)
-                {
-                    Main.main.undoRedo.add(new SequenceCommand(tr("Remove tags from multipolygon inner ways"), list));
-                }
-            }
-             */
-
+        final Pair<SequenceCommand, Relation> commandAndRelation = createMultipolygonCommand(selectedWays, selectedRelations);
+        final Command command = commandAndRelation.a;
+        final Relation relation = commandAndRelation.b;
+        if (command == null) {
+            return;
+        }
+        Main.main.undoRedo.add(command);
+
+        // Use 'SwingUtilities.invokeLater' to make sure the relationListDialog
+        // knows about the new relation before we try to select it.
+        // (Yes, we are already in event dispatch thread. But DatasetEventManager
+        // uses 'SwingUtilities.invokeLater' to fire events so we have to do
+        // the same.)
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                Main.map.relationListDialog.selectRelation(relation);
+                if (Main.pref.getBoolean("multipoly.show-relation-editor", false)) {
+                    //Open relation edit window, if set up in preferences
+                    RelationEditor editor = RelationEditor.getEditor(Main.main.getEditLayer(), relation, null);
+
+                    editor.setModal(true);
+                    editor.setVisible(true);
+                }
+            }
+        });
+
+    }
+
+    private static Relation getSelectedMultipolygonRelation(Collection<Relation> selectedRelations) {
+        return  selectedRelations.size() == 1 && "multipolygon".equals(selectedRelations.iterator().next().get("type"))
+                ? selectedRelations.iterator().next()
+                : null;
+    }
+
+    /**
+     * Returns a {@link Pair} of the old multipolygon {@link Relation} (or null) and the newly created/modified multipolygon {@link Relation}.
+     */
+    public static Pair<Relation, Relation> createMultipolygonRelation(Collection<Way> selectedWays, Collection<Relation> selectedRelations) {
+
+        final Relation selectedMultipolygonRelation = getSelectedMultipolygonRelation(selectedRelations);
+        if (selectedMultipolygonRelation != null) {
+            // add ways of existing relation to include them in polygon analysis
+            selectedWays = new HashSet<Way>(selectedWays);
+            selectedWays.addAll(Utils.filteredCollection(selectedMultipolygonRelation.getMemberPrimitives(), Way.class));
+        }
+
+        final MultipolygonCreate polygon = analyzeWays(selectedWays);
+        if (polygon == null) {
+            return null; //could not make multipolygon.
+        }
+
+        if (selectedMultipolygonRelation != null) {
+            return Pair.create(selectedMultipolygonRelation, createRelation(polygon, new Relation(selectedMultipolygonRelation)));
         } else {
-            //Just add the relation
-            List<Command> list = this.removeTagsFromWaysIfNeeded(relation);
+            return Pair.create(null, createRelation(polygon, new Relation()));
+        }
+    }
+
+    /**
+     * Returns a pair of a multipolygon creating/modifying {@link Command} as well as the multipolygon {@link Relation}.
+     */
+    public static Pair<SequenceCommand, Relation> createMultipolygonCommand(Collection<Way> selectedWays, Collection<Relation> selectedRelations) {
+
+        final Pair<Relation, Relation> rr = createMultipolygonRelation(selectedWays, selectedRelations);
+        if (rr == null) {
+            return null;
+        }
+        final Relation existingRelation = rr.a;
+        final Relation relation = rr.b;
+
+        final List<Command> list = removeTagsFromWaysIfNeeded(relation);
+        final String commandName;
+        if (existingRelation == null) {
             list.add(new AddCommand(relation));
-            Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list));
-            // Use 'SwingUtilities.invokeLater' to make sure the relationListDialog
-            // knows about the new relation before we try to select it.
-            // (Yes, we are already in event dispatch thread. But DatasetEventManager
-            // uses 'SwingUtilities.invokeLater' to fire events so we have to do
-            // the same.)
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    Main.map.relationListDialog.selectRelation(relation);
-                }
-            });
-        }
-
-
+            commandName = tr("Create multipolygon");
+        } else {
+            list.add(new ChangeCommand(existingRelation, relation));
+            commandName = tr("Update multipolygon");
+        }
+        return Pair.create(new SequenceCommand(commandName, list), relation);
     }
 
@@ -152,4 +192,8 @@
     @Override protected void updateEnabledState(Collection < ? extends OsmPrimitive > selection) {
         setEnabled(selection != null && !selection.isEmpty());
+        putValue(NAME, getSelectedMultipolygonRelation(getCurrentDataSet().getSelectedRelations()) != null
+                ? tr("Update multipolygon")
+                : tr("Create multipolygon")
+        );
     }
 
@@ -159,5 +203,5 @@
      * @return <code>null</code>, if there was a problem with the ways.
      */
-    private MultipolygonCreate analyzeWays(Collection < Way > selectedWays) {
+    private static MultipolygonCreate analyzeWays(Collection < Way > selectedWays) {
 
         MultipolygonCreate pol = new MultipolygonCreate();
@@ -179,21 +223,31 @@
      * @return multipolygon relation
      */
-    private Relation createRelation(MultipolygonCreate pol) {
+    private static Relation createRelation(MultipolygonCreate pol, final Relation rel) {
         // Create new relation
-        Relation rel = new Relation();
         rel.put("type", "multipolygon");
         // Add ways to it
         for (JoinedPolygon jway:pol.outerWays) {
-            for (Way way:jway.ways) {
-                rel.addMember(new RelationMember("outer", way));
-            }
+            addMembers(jway, rel, "outer");
         }
 
         for (JoinedPolygon jway:pol.innerWays) {
-            for (Way way:jway.ways) {
-                rel.addMember(new RelationMember("inner", way));
-            }
+            addMembers(jway, rel, "inner");
         }
         return rel;
+    }
+
+    private static void addMembers(JoinedPolygon polygon, Relation rel, String role) {
+        final int count = rel.getMembersCount();
+        final HashSet<Way> ways = new HashSet<Way>(polygon.ways);
+        for (int i = 0; i < count; i++) {
+            final RelationMember m = rel.getMember(i);
+            if (ways.contains(m.getMember()) && !role.equals(m.getRole())) {
+                rel.setMember(i, new RelationMember(role, m.getMember()));
+            }
+        }
+        ways.removeAll(rel.getMemberPrimitives());
+        for (final Way way : ways) {
+            rel.addMember(new RelationMember(role, way));
+        }
     }
 
@@ -206,5 +260,5 @@
      * @return a list of commands to execute
      */
-    private List<Command> removeTagsFromWaysIfNeeded( Relation relation ) {
+    private static List<Command> removeTagsFromWaysIfNeeded( Relation relation ) {
         Map<String, String> values = new HashMap<String, String>();
 
Index: /trunk/src/org/openstreetmap/josm/data/osm/Relation.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 6563)
+++ /trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 6564)
@@ -5,4 +5,5 @@
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -14,4 +15,5 @@
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.tools.CopyList;
+import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -319,21 +321,5 @@
      */
     public void removeMembersFor(OsmPrimitive primitive) {
-        if (primitive == null)
-            return;
-
-        boolean locked = writeLock();
-        try {
-            List<RelationMember> todelete = new ArrayList<RelationMember>();
-            for (RelationMember member: members) {
-                if (member.getMember() == primitive) {
-                    todelete.add(member);
-                }
-            }
-            List<RelationMember> members = getMembers();
-            members.removeAll(todelete);
-            setMembers(members);
-        } finally {
-            writeUnlock(locked);
-        }
+        removeMembersFor(Collections.singleton(primitive));
     }
 
@@ -356,4 +342,17 @@
 
     /**
+     * Obtains all members with member.member == primitive
+     * @param primitives the primitives to check for
+     */
+    public Collection<RelationMember> getMembersFor(final Collection<? extends OsmPrimitive> primitives) {
+        return Utils.filter(getMembers(), new Predicate<RelationMember>() {
+            @Override
+            public boolean evaluate(RelationMember member) {
+                return primitives.contains(member.getMember());
+            }
+        });
+    }
+
+    /**
      * removes all members with member.member == primitive
      *
@@ -367,12 +366,6 @@
         boolean locked = writeLock();
         try {
-            List<RelationMember> todelete = new ArrayList<RelationMember>();
-            for (RelationMember member: members) {
-                if (primitives.contains(member.getMember())) {
-                    todelete.add(member);
-                }
-            }
             List<RelationMember> members = getMembers();
-            members.removeAll(todelete);
+            members.removeAll(getMembersFor(primitives));
             setMembers(members);
         } finally {
Index: /trunk/test/data/create_multipolygon.osm
===================================================================
--- /trunk/test/data/create_multipolygon.osm	(revision 6564)
+++ /trunk/test/data/create_multipolygon.osm	(revision 6564)
@@ -0,0 +1,60 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version='0.6' upload='true' generator='JOSM'>
+  <node id='-38' action='modify' visible='true' lat='47.265124621055826' lon='11.28482073183536' />
+  <node id='-36' action='modify' visible='true' lat='47.253175055149' lon='11.261554365976664' />
+  <node id='-34' action='modify' visible='true' lat='47.23274480805068' lon='11.301709059176806' />
+  <node id='-32' action='modify' visible='true' lat='47.25500424514393' lon='11.302876869046163' />
+  <node id='-30' action='modify' visible='true' lat='47.256162699461036' lon='11.282305449039825' />
+  <node id='-28' action='modify' visible='true' lat='47.2492725719865' lon='11.277185051920343' />
+  <node id='-26' action='modify' visible='true' lat='47.24299140935173' lon='11.298564955682387' />
+  <node id='-24' action='modify' visible='true' lat='47.25354089820264' lon='11.296678493585736' />
+  <node id='-22' action='modify' visible='true' lat='47.252316770203464' lon='11.288373497503738' />
+  <node id='-20' action='modify' visible='true' lat='47.25145444588241' lon='11.284054104666238' />
+  <node id='-18' action='modify' visible='true' lat='47.246452687934294' lon='11.294598504828375' />
+  <node id='-16' action='modify' visible='true' lat='47.251713144653' lon='11.293328095170287' />
+  <node id='-14' action='modify' visible='true' lat='47.261370327868704' lon='11.285451555290134' />
+  <node id='-12' action='modify' visible='true' lat='47.257317974382424' lon='11.274780114162187' />
+  <node id='-10' action='modify' visible='true' lat='47.2567144058372' lon='11.287865333640504' />
+  <node id='-8' action='modify' visible='true' lat='47.25456741408533' lon='11.285796564093733' />
+  <node id='-6' action='modify' visible='true' lat='47.25353087229522' lon='11.281933808372019' />
+  <node id='-4' action='modify' visible='true' lat='47.25267723441035' lon='11.285347406451674' />
+  <way id='-48' action='modify' visible='true'>
+    <nd ref='-38' />
+    <nd ref='-36' />
+    <nd ref='-34' />
+    <nd ref='-32' />
+    <nd ref='-38' />
+    <tag k='landuse' v='forest' />
+    <tag k='ref' v='1' />
+  </way>
+  <way id='-46' action='modify' visible='true'>
+    <nd ref='-30' />
+    <nd ref='-28' />
+    <nd ref='-26' />
+    <nd ref='-24' />
+    <nd ref='-30' />
+    <tag k='ref' v='1.1' />
+  </way>
+  <way id='-44' action='modify' visible='true'>
+    <nd ref='-22' />
+    <nd ref='-20' />
+    <nd ref='-18' />
+    <nd ref='-16' />
+    <nd ref='-22' />
+    <tag k='ref' v='1.1.1' />
+  </way>
+  <way id='-42' action='modify' visible='true'>
+    <nd ref='-14' />
+    <nd ref='-12' />
+    <nd ref='-10' />
+    <nd ref='-14' />
+    <tag k='ref' v='1.2' />
+  </way>
+  <way id='-40' action='modify' visible='true'>
+    <nd ref='-8' />
+    <nd ref='-6' />
+    <nd ref='-4' />
+    <nd ref='-8' />
+    <tag k='ref' v='1.1.2' />
+  </way>
+</osm>
Index: /trunk/test/unit/org/openstreetmap/josm/actions/CreateMultipolygonActionTest.groovy
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/actions/CreateMultipolygonActionTest.groovy	(revision 6564)
+++ /trunk/test/unit/org/openstreetmap/josm/actions/CreateMultipolygonActionTest.groovy	(revision 6564)
@@ -0,0 +1,63 @@
+package org.openstreetmap.josm.actions
+
+import org.openstreetmap.TestUtils
+import org.openstreetmap.josm.Main
+import org.openstreetmap.josm.actions.search.SearchCompiler
+import org.openstreetmap.josm.data.osm.Relation
+import org.openstreetmap.josm.data.osm.Way
+import org.openstreetmap.josm.data.projection.Projections
+import org.openstreetmap.josm.io.OsmReader
+import org.openstreetmap.josm.tools.Utils
+
+class CreateMultipolygonActionTest extends GroovyTestCase {
+
+    @Override
+    void setUp() {
+        Main.initApplicationPreferences()
+        Main.setProjection(Projections.getProjectionByCode("EPSG:3857"));
+    }
+
+    def getRefToRoleMap(Relation relation) {
+        def refToRole = new TreeMap<String, String>()
+        for (i in relation.getMembers()) {
+            refToRole.put(i.member.get("ref"), i.role);
+        }
+        return refToRole;
+    }
+
+    void testCreate1() {
+        def ds = OsmReader.parseDataSet(new FileInputStream(TestUtils.getTestDataRoot() + "create_multipolygon.osm"), null);
+        def mp = CreateMultipolygonAction.createMultipolygonCommand(ds.getWays(), Collections.emptyList())
+        assert mp.a.getDescriptionText() == "Sequence: Create multipolygon"
+        assert getRefToRoleMap(mp.b).toString() == "[1:outer, 1.1:inner, 1.1.1:outer, 1.1.2:outer, 1.2:inner]"
+    }
+
+    void testCreate2() {
+        def ds = OsmReader.parseDataSet(new FileInputStream(TestUtils.getTestDataRoot() + "create_multipolygon.osm"), null);
+        def ways = Utils.filter(ds.getWays(), SearchCompiler.compile("ref=1 OR ref:1.1.", false, false))
+        def mp = CreateMultipolygonAction.createMultipolygonCommand(ways as Collection<Way>, Collections.emptyList())
+        assert getRefToRoleMap(mp.b).toString() == "[1:outer, 1.1.1:inner, 1.1.2:inner]"
+    }
+
+    void testUpdate1() {
+        def ds = OsmReader.parseDataSet(new FileInputStream(TestUtils.getTestDataRoot() + "create_multipolygon.osm"), null);
+        def ways = Utils.filter(ds.getWays(), SearchCompiler.compile("ref=\".*1\$\"", false, true))
+        def mp = CreateMultipolygonAction.createMultipolygonCommand(ways as Collection<Way>, Collections.emptyList())
+        assert mp.b.getMembersCount() == 3
+        assert getRefToRoleMap(mp.b).toString() == "[1:outer, 1.1:inner, 1.1.1:outer]"
+        def ways2 = Utils.filter(ds.getWays(), SearchCompiler.compile("ref=1.2", false, true))
+        def mp2 = CreateMultipolygonAction.createMultipolygonCommand(ways2 as Collection<Way>, Collections.singleton(mp.b))
+        assert mp2.b.getMembersCount() == 4
+        assert getRefToRoleMap(mp2.b).toString() == "[1:outer, 1.1:inner, 1.1.1:outer, 1.2:inner]"
+    }
+
+    void testUpdate2() {
+        def ds = OsmReader.parseDataSet(new FileInputStream(TestUtils.getTestDataRoot() + "create_multipolygon.osm"), null);
+        def ways = Utils.filter(ds.getWays(), SearchCompiler.compile("ref=1 OR ref:1.1.1", false, false))
+        def mp = CreateMultipolygonAction.createMultipolygonCommand(ways as Collection<Way>, Collections.emptyList())
+        assert getRefToRoleMap(mp.b).toString() == "[1:outer, 1.1.1:inner]"
+        def ways2 = Utils.filter(ds.getWays(), SearchCompiler.compile("ref=1.1 OR ref=1.2 OR ref=1.1.2", false, true))
+        def mp2 = CreateMultipolygonAction.createMultipolygonCommand(ways2 as Collection<Way>, Collections.singleton(mp.b))
+        assert getRefToRoleMap(mp2.b).toString() == "[1:outer, 1.1:inner, 1.1.1:outer, 1.1.2:outer, 1.2:inner]"
+    }
+}
