Index: trunk/src/org/openstreetmap/josm/actions/PasteAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/PasteAction.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/actions/PasteAction.java	(revision 2932)
@@ -92,9 +92,9 @@
             copy.clearOsmId();
             if (data instanceof NodeData) {
-                newNodeIds.put(data.getId(), copy.getId());
+                newNodeIds.put(data.getUniqueId(), copy.getUniqueId());
             } else if (data instanceof WayData) {
-                newWayIds.put(data.getId(), copy.getId());
+                newWayIds.put(data.getUniqueId(), copy.getUniqueId());
             } else if (data instanceof RelationData) {
-                newRelationIds.put(data.getId(), copy.getId());
+                newRelationIds.put(data.getUniqueId(), copy.getUniqueId());
             }
             bufferCopy.add(copy);
Index: trunk/src/org/openstreetmap/josm/command/Command.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/Command.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/command/Command.java	(revision 2932)
@@ -1,6 +1,4 @@
 //License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.command;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.util.Collection;
@@ -125,5 +123,5 @@
             PrimitiveData to = cloneMap.get(t);
             Main.debug("now: " + t.getId() + " hashCode: " + t.hashCode());
-            Main.debug("orig: " + to.getId() + " hashCode: " + to.hashCode());
+            Main.debug("orig: " + to.getUniqueId() + " hashCode: " + to.hashCode());
         }
         return o;
Index: trunk/src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 2932)
@@ -71,11 +71,10 @@
 
     /**
-     * Create new complete node
+     * Create new node
      * @param id
      * @param version
      */
     public Node(long id, int version) {
-        super(id, false);
-        setOsmId(id, version);
+        super(id, version, false);
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 2932)
@@ -223,7 +223,21 @@
     }
 
-    protected OsmPrimitive(PrimitiveData data) {
-        version = data.getVersion();
-        id = data.getId();
+    /**
+     * Creates a new primitive for the given id and version.
+     *
+     * If allowNegativeId is set, provided id can be < 0 and will be set to primitive without any processing.
+     * If allowNegativeId is not set, then id will have to be 0 (in that case new unique id will be generated) or
+     * positive number.
+     * 
+     * If id is not > 0 version is ignored and set to 0.
+     *
+     * @param id
+     * @param version
+     * @param allowNegativeId
+     * @throws IllegalArgumentException thrown if id < 0 and allowNegativeId is false
+     */
+    protected OsmPrimitive(long id, int version, boolean allowNegativeId) throws IllegalArgumentException {
+        this(id, allowNegativeId);
+        this.version = (id > 0 ? version : 0);
     }
 
@@ -1161,5 +1175,5 @@
     public void load(PrimitiveData data) {
         setKeys(data.getKeys());
-        timestamp = data.getTimestamp();
+        setTimestamp(data.getTimestamp());
         user = data.getUser();
         setChangesetId(data.getChangesetId());
@@ -1180,5 +1194,5 @@
         data.getKeys().clear();
         data.getKeys().putAll(getKeys());
-        data.setTimestamp(timestamp);
+        data.setTimestamp(getTimestamp());
         data.setUser(user);
         data.setDeleted(isDeleted());
Index: trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java	(revision 2932)
@@ -4,4 +4,5 @@
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -47,5 +48,5 @@
     private User user;
     private int version;
-    private int timestamp;
+    private Date timestamp = new Date();
     private int changesetId;
 
@@ -69,5 +70,5 @@
     }
     public long getId() {
-        return id;
+        return id > 0 ? id : 0;
     }
     public void setId(long id) {
@@ -86,8 +87,8 @@
         this.version = version;
     }
-    public int getTimestamp() {
+    public Date getTimestamp() {
         return timestamp;
     }
-    public void setTimestamp(int timestamp) {
+    public void setTimestamp(Date timestamp) {
         this.timestamp = timestamp;
     }
@@ -194,4 +195,13 @@
     }
 
+    /**
+     * Returns a PrimitiveId object for this primitive
+     *
+     * @return the PrimitiveId for this primitive
+     */
+    public PrimitiveId getPrimitiveId() {
+        return new SimplePrimitiveId(getUniqueId(), getType());
+    }
+
     public boolean isNew() {
         return id <= 0;
Index: trunk/src/org/openstreetmap/josm/data/osm/Relation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 2932)
@@ -172,11 +172,10 @@
 
     /**
-     * Creates new complete relation
+     * Creates new relation
      * @param id
      * @param version
      */
     public Relation(long id, int version) {
-        super(id, false);
-        setOsmId(id, version);
+        super(id, version, false);
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 2932)
@@ -183,11 +183,10 @@
 
     /**
-     * Creates new way with given id and version. Way is marked as complete
+     * Creates new way with given id and version.
      * @param id
      * @param version
      */
     public Way(long id, int version) {
-        super(id, false);
-        setOsmId(id, version);
+        super(id, version, false);
     }
 
Index: trunk/src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmReader.java	(revision 2931)
+++ trunk/src/org/openstreetmap/josm/io/OsmReader.java	(revision 2932)
@@ -8,5 +8,4 @@
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -24,12 +23,16 @@
 import org.openstreetmap.josm.data.osm.DataSource;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.NodeData;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.PrimitiveData;
 import org.openstreetmap.josm.data.osm.PrimitiveId;
 import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationData;
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WayData;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
@@ -66,11 +69,4 @@
      * longs too, but in contrast to internal ids negative values are used
      * to identify primitives unknown to the OSM server
-     *
-     * The keys are strings composed as follows
-     * <ul>
-     *   <li>"n" + id  for nodes</li>
-     *   <li>"w" + id  for nodes</li>
-     *   <li>"r" + id  for nodes</li>
-     * </ul>
      */
     private Map<PrimitiveId, OsmPrimitive> externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>();
@@ -86,68 +82,4 @@
     }
 
-    private static class OsmPrimitiveData {
-        public long id = 0;
-        public boolean modified = false;
-        public boolean deleted = false;
-        public Date timestamp = new Date();
-        public User user = null;
-        public boolean visible = true;
-        public int version = 0;
-        public LatLon latlon = new LatLon(0,0);
-        private OsmPrimitive primitive;
-        private int changesetId;
-
-        public void copyTo(OsmPrimitive osm) {
-            // It's not necessary to call clearOsmId for id < 0. The same thing is done by parameterless constructor
-            if (id > 0) {
-                osm.setOsmId(id, version);
-            }
-            osm.setDeleted(deleted);
-            osm.setModified(modified | deleted);
-            osm.setTimestamp(timestamp);
-            osm.setUser(user);
-            if (!osm.isNew() && changesetId > 0) {
-                osm.setChangesetId(changesetId);
-            } else if (osm.isNew() && changesetId > 0) {
-                System.out.println(tr("Warning: ignoring changeset id {0} for new object with external id {1} and internal id {2}",
-                        changesetId,
-                        id,
-                        osm.getUniqueId()
-                ));
-            }
-            if (! osm.isNew()) {
-                // ignore visible attribute for objects not yet known to the server
-                //
-                osm.setVisible(visible);
-            }
-            osm.mappaintStyle = null;
-        }
-
-        public Node createNode() {
-            Node node = new Node();
-            node.setCoor(latlon);
-            copyTo(node);
-            primitive = node;
-            return node;
-        }
-
-        public Way createWay() {
-            Way way = new Way();
-            copyTo(way);
-            primitive = way;
-            return way;
-        }
-        public Relation createRelation() {
-            Relation relation= new Relation();
-            copyTo(relation);
-            primitive = relation;
-            return relation;
-        }
-
-        public void rememberTag(String key, String value) {
-            primitive.put(key, value);
-        }
-    }
-
     /**
      * Used as a temporary storage for relation members, before they
@@ -155,5 +87,5 @@
      */
     private static class RelationMemberData {
-        public String type;
+        public OsmPrimitiveType type;
         public long id;
         public String role;
@@ -184,5 +116,6 @@
          * The current osm primitive to be read.
          */
-        private OsmPrimitiveData current;
+        private OsmPrimitive currentPrimitive;
+        private long currentExternalId;
         private String generator;
 
@@ -229,17 +162,23 @@
 
             } else if (qName.equals("node")) {
-                current = new OsmPrimitiveData();
-                current.latlon = new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon"));
-                readCommon(atts, current);
-                Node n = current.createNode();
-                externalIdMap.put(new SimplePrimitiveId(current.id, OsmPrimitiveType.NODE), n);
+                NodeData nd = new NodeData();
+                nd.setCoor(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
+                readCommon(atts, nd);
+                Node n = new Node(nd.getId(), nd.getVersion());
+                n.load(nd);
+                externalIdMap.put(nd.getPrimitiveId(), n);
+                currentPrimitive = n;
+                currentExternalId = nd.getUniqueId();
             } else if (qName.equals("way")) {
-                current = new OsmPrimitiveData();
-                readCommon(atts, current);
-                Way w = current.createWay();
-                externalIdMap.put(new SimplePrimitiveId(current.id, OsmPrimitiveType.WAY), w);
-                ways.put(current.id, new ArrayList<Long>());
+                WayData wd = new WayData();
+                readCommon(atts, wd);
+                Way w = new Way(wd.getId(), wd.getVersion());
+                w.load(wd);
+                externalIdMap.put(wd.getPrimitiveId(), w);
+                ways.put(wd.getUniqueId(), new ArrayList<Long>());
+                currentPrimitive = w;
+                currentExternalId = wd.getUniqueId();
             } else if (qName.equals("nd")) {
-                Collection<Long> list = ways.get(current.id);
+                Collection<Long> list = ways.get(currentExternalId);
                 if (list == null) {
                     throwException(
@@ -249,5 +188,5 @@
                 if (atts.getValue("ref") == null) {
                     throwException(
-                            tr("Missing mandatory attribute ''{0}'' on <nd> of way {1}.", "ref", current.id)
+                            tr("Missing mandatory attribute ''{0}'' on <nd> of way {1}.", "ref", currentPrimitive.getUniqueId())
                     );
                 }
@@ -258,6 +197,6 @@
                     );
                 }
-                if (current.deleted) {
-                    logger.info(tr("Deleted way {0} contains nodes", current.id));
+                if (currentPrimitive.isDeleted()) {
+                    logger.info(tr("Deleted way {0} contains nodes", currentPrimitive.getUniqueId()));
                 } else {
                     list.add(id);
@@ -267,11 +206,14 @@
 
             } else if (qName.equals("relation")) {
-                current = new OsmPrimitiveData();
-                readCommon(atts, current);
-                Relation r = current.createRelation();
-                externalIdMap.put(new SimplePrimitiveId(current.id, OsmPrimitiveType.RELATION), r);
-                relations.put(current.id, new LinkedList<RelationMemberData>());
+                RelationData rd = new RelationData();
+                readCommon(atts, rd);
+                Relation r = new Relation(rd.getId(), rd.getVersion());
+                r.load(rd);
+                externalIdMap.put(rd.getPrimitiveId(), r);
+                relations.put(r.getUniqueId(), new LinkedList<RelationMemberData>());
+                currentPrimitive = r;
+                currentExternalId = rd.getUniqueId();
             } else if (qName.equals("member")) {
-                Collection<RelationMemberData> list = relations.get(current.id);
+                Collection<RelationMemberData> list = relations.get(currentExternalId);
                 if (list == null) {
                     throwException(
@@ -282,19 +224,20 @@
                 String value = atts.getValue("ref");
                 if (value == null) {
-                    throwException(tr("Missing attribute ''ref'' on member in relation {0}.",current.id));
+                    throwException(tr("Missing attribute ''ref'' on member in relation {0}.",currentPrimitive.getUniqueId()));
                 }
                 try {
                     emd.id = Long.parseLong(value);
                 } catch(NumberFormatException e) {
-                    throwException(tr("Illegal value for attribute ''ref'' on member in relation {0}. Got {1}", Long.toString(current.id),value));
+                    throwException(tr("Illegal value for attribute ''ref'' on member in relation {0}. Got {1}", Long.toString(currentPrimitive.getUniqueId()),value));
                 }
                 value = atts.getValue("type");
                 if (value == null) {
-                    throwException(tr("Missing attribute ''type'' on member {0} in relation {1}.", Long.toString(emd.id), Long.toString(current.id)));
-                }
-                if (! (value.equals("way") || value.equals("node") || value.equals("relation"))) {
-                    throwException(tr("Illegal value for attribute ''type'' on member {0} in relation {1}. Got {2}.", Long.toString(emd.id), Long.toString(current.id), value));
-                }
-                emd.type= value;
+                    throwException(tr("Missing attribute ''type'' on member {0} in relation {1}.", Long.toString(emd.id), Long.toString(currentPrimitive.getUniqueId())));
+                }
+                try {
+                    emd.type = OsmPrimitiveType.fromApiTypeName(value);
+                } catch(IllegalArgumentException e) {
+                    throwException(tr("Illegal value for attribute ''type'' on member {0} in relation {1}. Got {2}.", Long.toString(emd.id), Long.toString(currentPrimitive.getUniqueId()), value));
+                }
                 value = atts.getValue("role");
                 emd.role = value;
@@ -304,6 +247,6 @@
                 }
 
-                if (current.deleted) {
-                    logger.info(tr("Deleted relation {0} contains members", current.id));
+                if (currentPrimitive.isDeleted()) {
+                    logger.info(tr("Deleted relation {0} contains members", currentPrimitive.getUniqueId()));
                 } else {
                     list.add(emd);
@@ -315,5 +258,5 @@
                 String key = atts.getValue("k");
                 String value = atts.getValue("v");
-                current.rememberTag(key, value);
+                currentPrimitive.put(key, value);
             } else {
                 System.out.println(tr("Undefined element ''{0}'' found in input stream. Skipping.", qName));
@@ -342,7 +285,7 @@
          * Read out the common attributes from atts and put them into this.current.
          */
-        void readCommon(Attributes atts, OsmPrimitiveData current) throws SAXException {
-            current.id = getLong(atts, "id");
-            if (current.id == 0) {
+        void readCommon(Attributes atts, PrimitiveData current) throws SAXException {
+            current.setId(getLong(atts, "id"));
+            if (current.getUniqueId() == 0) {
                 throwException(tr("Illegal object with ID=0."));
             }
@@ -350,5 +293,5 @@
             String time = atts.getValue("timestamp");
             if (time != null && time.length() != 0) {
-                current.timestamp =  DateUtils.fromString(time);
+                current.setTimestamp(DateUtils.fromString(time));
             }
 
@@ -357,34 +300,34 @@
             // uid attribute added in 0.6 API
             String uid = atts.getValue("uid");
-            current.user = createUser(uid, user);
+            current.setUser(createUser(uid, user));
 
             // visible attribute added in 0.4 API
             String visible = atts.getValue("visible");
             if (visible != null) {
-                current.visible = Boolean.parseBoolean(visible);
-            }
-
-            String version = atts.getValue("version");
-            current.version = 0;
-            if (version != null) {
+                current.setVisible(Boolean.parseBoolean(visible));
+            }
+
+            String versionString = atts.getValue("version");
+            int version = 0;
+            if (versionString != null) {
                 try {
-                    current.version = Integer.parseInt(version);
+                    version = Integer.parseInt(versionString);
                 } catch(NumberFormatException e) {
-                    throwException(tr("Illegal value for attribute ''version'' on OSM primitive with ID {0}. Got {1}.", Long.toString(current.id), version));
+                    throwException(tr("Illegal value for attribute ''version'' on OSM primitive with ID {0}. Got {1}.", Long.toString(current.getUniqueId()), versionString));
                 }
                 if (ds.getVersion().equals("0.6")){
-                    if (current.version <= 0 && current.id > 0) {
-                        throwException(tr("Illegal value for attribute ''version'' on OSM primitive with ID {0}. Got {1}.", Long.toString(current.id), version));
-                    } else if (current.version < 0 && current.id  <=0) {
-                        System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.id, current.version, 0, "0.6"));
-                        current.version = 0;
+                    if (version <= 0 && current.getUniqueId() > 0) {
+                        throwException(tr("Illegal value for attribute ''version'' on OSM primitive with ID {0}. Got {1}.", Long.toString(current.getUniqueId()), versionString));
+                    } else if (version < 0 && current.getUniqueId() <= 0) {
+                        System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.getUniqueId(), version, 0, "0.6"));
+                        version = 0;
                     }
                 } else if (ds.getVersion().equals("0.5")) {
-                    if (current.version <= 0 && current.id > 0) {
-                        System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.id, current.version, 1, "0.5"));
-                        current.version = 1;
-                    } else if (current.version < 0 && current.id  <=0) {
-                        System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.id, current.version, 0, "0.5"));
-                        current.version = 0;
+                    if (version <= 0 && current.getUniqueId() > 0) {
+                        System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.getUniqueId(), version, 1, "0.5"));
+                        version = 1;
+                    } else if (version < 0 && current.getUniqueId() <= 0) {
+                        System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.getUniqueId(), version, 0, "0.5"));
+                        version = 0;
                     }
                 } else {
@@ -395,16 +338,17 @@
                 // version expected for OSM primitives with an id assigned by the server (id > 0), since API 0.6
                 //
-                if (current.id > 0 && ds.getVersion() != null && ds.getVersion().equals("0.6")) {
-                    throwException(tr("Missing attribute ''version'' on OSM primitive with ID {0}.", Long.toString(current.id)));
-                } else if (current.id > 0 && ds.getVersion() != null && ds.getVersion().equals("0.5")) {
+                if (current.getUniqueId() > 0 && ds.getVersion() != null && ds.getVersion().equals("0.6")) {
+                    throwException(tr("Missing attribute ''version'' on OSM primitive with ID {0}.", Long.toString(current.getUniqueId())));
+                } else if (current.getUniqueId() > 0 && ds.getVersion() != null && ds.getVersion().equals("0.5")) {
                     // default version in 0.5 files for existing primitives
-                    System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.id, current.version, 1, "0.5"));
-                    current.version= 1;
-                } else if (current.id <= 0 && ds.getVersion() != null && ds.getVersion().equals("0.5")) {
+                    System.out.println(tr("WARNING: Normalizing value of attribute ''version'' of element {0} to {2}, API version is ''{3}''. Got {1}.", current.getUniqueId(), version, 1, "0.5"));
+                    version= 1;
+                } else if (current.getUniqueId() <= 0 && ds.getVersion() != null && ds.getVersion().equals("0.5")) {
                     // default version in 0.5 files for new primitives, no warning necessary. This is
                     // (was) legal in API 0.5
-                    current.version= 0;
-                }
-            }
+                    version= 0;
+                }
+            }
+            current.setVersion(version);
 
             String action = atts.getValue("action");
@@ -412,20 +356,20 @@
                 // do nothing
             } else if (action.equals("delete")) {
-                current.deleted = true;
+                current.setDeleted(true);
             } else if (action.startsWith("modify")) { //FIXME: why startsWith()? why not equals()?
-                current.modified = true;
+                current.setModified(true);
             }
 
             String v = atts.getValue("changeset");
             if (v == null) {
-                current.changesetId = 0;
+                current.setChangesetId(0);
             } else {
                 try {
-                    current.changesetId = Integer.parseInt(v);
+                    current.setChangesetId(Integer.parseInt(v));
                 } catch(NumberFormatException e) {
-                    if (current.id <= 0) {
+                    if (current.getUniqueId() <= 0) {
                         // for a new primitive we just log a warning
-                        System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.id));
-                        current.changesetId = 0;
+                        System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.getUniqueId()));
+                        current.setChangesetId(0);
                     } else {
                         // for an existing primitive this is a problem
@@ -433,9 +377,9 @@
                     }
                 }
-                if (current.changesetId <=0) {
-                    if (current.id <= 0) {
+                if (current.getChangesetId() <=0) {
+                    if (current.getUniqueId() <= 0) {
                         // for a new primitive we just log a warning
-                        System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.id));
-                        current.changesetId = 0;
+                        System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.getUniqueId()));
+                        current.setChangesetId(0);
                     } else {
                         // for an existing primitive this is a problem
@@ -475,10 +419,7 @@
                     if (id <= 0)
                         throw new IllegalDataException (
-                                tr(
-                                        "Way with external ID ''{0}'' includes missing node with external ID ''{1}''.",
+                                tr("Way with external ID ''{0}'' includes missing node with external ID ''{1}''.",
                                         externalWayId,
-                                        id
-                                )
-                        );
+                                        id));
                     // create an incomplete node if necessary
                     //
@@ -490,19 +431,16 @@
                 }
                 if (n.isDeleted()) {
-                    logger.warning(tr("Deleted node {0} was removed from way {1}", id, w.getId()));
-                } else {
-                    wayNodes.add(n);
-                }
+                    logger.warning(tr("Deleted node {0} is part of way {1}", id, w.getId()));
+                }
+                wayNodes.add(n);
             }
             w.setNodes(wayNodes);
             if (w.hasIncompleteNodes()) {
                 if (logger.isLoggable(Level.FINE)) {
-                    logger.fine(tr("Marked way {0} with {1} nodes incomplete because at least one node was missing in the " +
-                            "loaded data and is therefore incomplete too.", externalWayId, w.getNodesCount()));
-                }
-                ds.addPrimitive(w);
-            } else {
-                ds.addPrimitive(w);
-            }
+                    logger.fine(tr("Way {0} with {1} nodes has incomplete nodes because at least one node was missing in the loaded data.",
+                            externalWayId, w.getNodesCount()));
+                }
+            }
+            ds.addPrimitive(w);
         }
     }
@@ -538,13 +476,5 @@
 
                 // lookup the member from the map of already created primitives
-                //
-                try {
-                    OsmPrimitiveType type = OsmPrimitiveType.fromApiTypeName(rm.type);
-                    primitive = externalIdMap.get(new SimplePrimitiveId(rm.id, type));
-                } catch(IllegalArgumentException e) {
-                    throw new IllegalDataException(
-                            tr("Unknown relation member type ''{0}'' in relation with external id ''{1}''.", rm.type,externalRelationId)
-                    );
-                }
+                primitive = externalIdMap.get(new SimplePrimitiveId(rm.id, rm.type));
 
                 if (primitive == null) {
@@ -555,33 +485,31 @@
                         //
                         throw new IllegalDataException(
-                                tr(
-                                        "Relation with external id ''{0}'' refers to a missing primitive with external id ''{1}''.",
+                                tr("Relation with external id ''{0}'' refers to a missing primitive with external id ''{1}''.",
                                         externalRelationId,
-                                        rm.id
-                                )
-                        );
+                                        rm.id));
 
                     // member refers to OSM primitive which was not present in the parsed data
                     // -> create a new incomplete primitive and add it to the dataset
                     //
-                    if (rm.type.equals("node")) {
-                        primitive = new Node(rm.id);
-                    } else if (rm.type.equals("way")) {
-                        primitive = new Way(rm.id);
-                    } else if (rm.type.equals("relation")) {
-                        primitive = new Relation(rm.id);
-                    } else
-                        // can't happen, we've been testing for valid member types
-                        // at the beginning of this method
-                        //
-                        throw new AssertionError();
-                    ds.addPrimitive(primitive);
-                    externalIdMap.put(new SimplePrimitiveId(rm.id, OsmPrimitiveType.fromApiTypeName(rm.type)), primitive);
+                    primitive = ds.getPrimitiveById(rm.id, rm.type);
+                    if (primitive == null) {
+                        switch (rm.type) {
+                        case NODE:
+                            primitive = new Node(rm.id); break;
+                        case WAY:
+                            primitive = new Way(rm.id); break;
+                        case RELATION:
+                            primitive = new Relation(rm.id); break;
+                        default: throw new AssertionError(); // can't happen
+                        }
+
+                        ds.addPrimitive(primitive);
+                        externalIdMap.put(new SimplePrimitiveId(rm.id, rm.type), primitive);
+                    }
                 }
                 if (primitive.isDeleted()) {
-                    logger.warning(tr("Deleted member {0} was removed from relation {1}", primitive.getId(), relation.getId()));
-                } else {
-                    relationMembers.add(new RelationMember(rm.role, primitive));
-                }
+                    logger.warning(tr("Deleted member {0} is used by relation {1}", primitive.getId(), relation.getId()));
+                }
+                relationMembers.add(new RelationMember(rm.role, primitive));
             }
             relation.setMembers(relationMembers);
