Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 367)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 369)
@@ -26,5 +26,5 @@
 	/**
 	 * Map from primitives in the database to visited primitives. (Attention: The other way 
-	 * round than mergedPrims)
+	 * round than merged)
 	 */
 	public Map<OsmPrimitive, OsmPrimitive> conflicts = new HashMap<OsmPrimitive, OsmPrimitive>();
@@ -38,5 +38,5 @@
 	 * in ds.nodes instead.
 	 */
-	private final Map<OsmPrimitive, OsmPrimitive> mergedPrims
+	private final Map<OsmPrimitive, OsmPrimitive> merged
 		= new HashMap<OsmPrimitive, OsmPrimitive>();
 
@@ -51,5 +51,5 @@
 	 */
 	public void visit(Node other) {
-		if (mergeAfterId(mergedPrims, ds.nodes, other))
+		if (mergeAfterId(ds.nodes, other))
 			return;
 
@@ -64,5 +64,5 @@
 			ds.nodes.add(other);
 		else {
-			mergedPrims.put(other, my);
+			merged.put(other, my);
 			mergeCommon(my, other);
 			if (my.modified && !other.modified)
@@ -77,5 +77,54 @@
 
 	private <T extends OsmPrimitive> void cloneFromExceptIncomplete(T myOsm, T otherOsm) {
-		if (!otherOsm.incomplete) {
+		if (myOsm instanceof Way) {
+            Way my = (Way)myOsm;
+            Way other = (Way)otherOsm;
+            HashMap<Long, Node> copy = new HashMap<Long, Node>();
+            for (Node n : my.nodes)
+                copy.put(n.id, n);
+            my.cloneFrom(other);
+            my.nodes.clear();
+            for (Node n : other.nodes) {
+                Node myN = copy.get(n.id);
+                if (n.incomplete && myN != null && !myN.incomplete) {
+                    merged.put(n, myN);
+                    my.nodes.add(myN);
+                } else
+                    my.nodes.add(n);
+            }
+		} else if (myOsm instanceof Relation) {
+            Relation my = (Relation)myOsm;
+            Relation other = (Relation)otherOsm;
+
+			HashMap<Long, OsmPrimitive>[] copy =
+				(HashMap<Long, OsmPrimitive>[]) new HashMap[3];
+			for (int i = 0; i < 3; i++) copy[i] = new HashMap<Long, OsmPrimitive>();
+
+			for (RelationMember m : my.members) {
+				int i;
+				if (m.member instanceof Node) i = 0; else
+				if (m.member instanceof Way) i = 1; else
+				if (m.member instanceof Relation) i = 2; else i = 3;
+				copy[i].put(m.member.id, m.member);
+			}
+
+			my.cloneFrom(other);
+			my.members.clear();
+			for (RelationMember m : other.members) {
+				int i;
+				if (m.member instanceof Node) i = 0; else
+				if (m.member instanceof Way) i = 1; else
+				if (m.member instanceof Relation) i = 2; else i = 3;
+				OsmPrimitive myP = copy[i].get(m.member.id);
+				if (m.member.incomplete && myP != null && !myP.incomplete) {
+					RelationMember mnew = new RelationMember(m);
+					mnew.member = myP;
+					my.members.add(mnew);
+					merged.put(m.member, mnew.member);
+				} else {
+					my.members.add(m);
+				}
+			}
+		} else {
 			myOsm.cloneFrom(otherOsm);
 		}
@@ -87,5 +136,6 @@
 	 */
 	public void visit(Way other) {
-		if (mergeAfterId(mergedPrims, ds.ways, other))
+		fixWay(other);
+		if (mergeAfterId(ds.ways, other))
 			return;
 
@@ -99,6 +149,11 @@
 		if (my == null) {
 			ds.ways.add(other);
+		} else if (my.incomplete && !other.incomplete) {
+			merged.put(other, my);
+			my.cloneFrom(other);
+		} else if (other.incomplete && !my.incomplete) {
+			merged.put(other, my);
 		} else {
-			mergedPrims.put(other, my);
+			merged.put(other, my);
 			mergeCommon(my, other);
 			if (my.modified && !other.modified)
@@ -123,5 +178,6 @@
 	 */
 	public void visit(Relation other) {
-		if (mergeAfterId(null, ds.relations, other))
+		fixRelation(other);
+		if (mergeAfterId(ds.relations, other))
 			return;
 
@@ -133,16 +189,30 @@
 			}
 		}
-		
+
 		if (my == null) {
 			// Add the relation and replace any incomplete segments that we already have
 			ds.relations.add(other);
-			// FIXME unclear!
-			/*
-			for (RelationMember em : other.getMembers()) {
+			/*for (RelationMember em : other.members) {
 				if (em.member.incomplete) {
-					for (Segment ourSegment : ds.segments) {
-						if (ourSegment.id == s.id) {
-							mergedSegments.put(s, ourSegment);
-							break;
+					if (em.member instanceof Node) {
+						for (Node ourN : ds.nodes) {
+							if (ourN.id == em.member.id) {
+								merged.put(em.member, ourN);
+								break;
+							}
+						}
+					} else if (em.member instanceof Way) {
+						for (Way ourW : ds.ways) {
+							if (ourW.id == em.member.id) {
+								merged.put(em.member, ourW);
+								break;
+							}
+						}
+					} else if (em.member instanceof Relation) {
+						for (Relation ourR : ds.relations) {
+							if (ourR.id == em.member.id) {
+								merged.put(em.member, ourR);
+								break;
+							}
 						}
 					}
@@ -150,5 +220,5 @@
 			}*/
 		} else {
-			mergedPrims.put(other, my);
+			merged.put(other, my);
 			mergeCommon(my, other);
 			if (my.modified && !other.modified)
@@ -165,22 +235,36 @@
 				}
 			}
-			// FIXME Unclear
-			/*
 			if (!same) {
-				HashMap<Long, Segment> copy = new HashMap<Long, Segment>();
-				for (Segment s : my.segments)
-					copy.put(s.id, s);
-				my.segments.clear();
-				for (Segment s : other.segments) {
-					Segment myS = copy.get(s.id);
-					if (s.incomplete && myS != null && !myS.incomplete) {
-						mergedSegments.put(s, myS);
-						my.segments.add(myS);
-					} else
-						my.segments.add(s);
-				}
+				/*HashMap<Long, OsmPrimitive>[] copy =
+					(HashMap<Long, OsmPrimitive>[]) new HashMap[3];
+				for (int i = 0; i < 3; i++) copy[i] = new HashMap<Long, OsmPrimitive>();
+
+				for (RelationMember m : my.members) {
+					int i;
+					if (m.member instanceof Node) i = 0; else
+					if (m.member instanceof Way) i = 1; else
+					if (m.member instanceof Relation) i = 2; else i = 3;
+					copy[i].put(m.member.id, m.member);
+				}
+
+				my.cloneFrom(other);
+				my.members.clear();
+				for (RelationMember m : other.members) {
+					int i;
+					if (m.member instanceof Node) i = 0; else
+					if (m.member instanceof Way) i = 1; else
+					if (m.member instanceof Relation) i = 2; else i = 3;
+					OsmPrimitive myP = copy[i].get(m.member.id);
+					if (m.member.incomplete && myP != null && !myP.incomplete) {
+						RelationMember mnew = new RelationMember(m);
+						mnew.member = myP;
+						my.members.add(mnew);
+						merged.put(m.member, mnew.member);
+					} else {
+						my.members.add(m);
+					}
+				}*/
 				my.modified = other.modified;
 			}
-			*/
 		}
 	}
@@ -204,5 +288,5 @@
 	    LinkedList<Node> newNodes = new LinkedList<Node>();
 	    for (Node n : w.nodes) {
-	    	Node otherN = (Node) mergedPrims.get(n);
+	    	Node otherN = (Node) merged.get(n);
 	    	newNodes.add(otherN == null ? n : otherN);
 	    	if (otherN != null)
@@ -219,5 +303,5 @@
 	    LinkedList<RelationMember> newMembers = new LinkedList<RelationMember>();
 	    for (RelationMember m : r.members) {
-	    	OsmPrimitive otherP = mergedPrims.get(m.member);
+	    	OsmPrimitive otherP = merged.get(m.member);
 			if (otherP == null) {
 				newMembers.add(m);
@@ -308,17 +392,15 @@
 	 * @return <code>true</code>, if no merge is needed or merge is performed already.
 	 */
-	private <P extends OsmPrimitive> boolean mergeAfterId(Map<OsmPrimitive,OsmPrimitive> merged, Collection<P> primitives, P other) {
+	private <P extends OsmPrimitive> boolean mergeAfterId(Collection<P> primitives, P other) {
 		for (P my : primitives) {
 			Date myd = my.timestamp == null ? new Date(0) : my.getTimestamp();
 			Date otherd = other.timestamp == null ? new Date(0) : other.getTimestamp();
 			if (my.realEqual(other, false)) {
-				if (merged != null)
-					merged.put(other, my);
+				merged.put(other, my);
 				return true; // no merge needed.
 			}
 			if (my.realEqual(other, true)) {
 				// they differ in modified/timestamp combination only. Auto-resolve it.
-				if (merged != null)
-					merged.put(other, my);
+				merged.put(other, my);
 				if (myd.before(otherd)) {
 					my.modified = other.modified;
@@ -328,25 +410,31 @@
 			}
 			if (my.id == other.id && my.id != 0) {
-				if (my.incomplete) {
-					return false;
+				if (my.incomplete || other.incomplete) {
+					if (my.incomplete) {
+						my.cloneFrom(other);
+					}
+					merged.put(other, my);
 				} else if (my.modified && other.modified) {
 					conflicts.put(my, other);
+					merged.put(other, my);
 				} else if (!my.modified && !other.modified) {
 					if (myd.before(otherd)) {
 						cloneFromExceptIncomplete(my, other);
+						merged.put(other, my);
 					}
 				} else if (other.modified) {
 					if (myd.after(otherd)) {
 						conflicts.put(my, other);
+						merged.put(other, my);
 					} else {
 						cloneFromExceptIncomplete(my, other);
+						merged.put(other, my);
 					}
 				} else if (my.modified) {
 					if (myd.before(otherd)) {
 						conflicts.put(my, other);
-					}
-				}
-				if (merged != null)
-					merged.put(other, my);
+						merged.put(other, my);
+					}
+				}
 				return true;
 			}
