Index: trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java	(revision 4602)
@@ -54,5 +54,5 @@
      * replies the base URL for browsing information about a user
      *
-     * @return the base URL, i.e. http://ww.openstreetmap.org/user
+     * @return the base URL, i.e. http://www.openstreetmap.org/user
      */
     static public String getBaseUserUrl() {
Index: trunk/src/org/openstreetmap/josm/data/osm/User.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/User.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/data/osm/User.java	(revision 4602)
@@ -1,4 +1,6 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.data.osm;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.BufferedReader;
@@ -35,4 +37,5 @@
     private static HashSet<Long> relicensingUsers = null;
     private static HashSet<Long> nonRelicensingUsers = null;
+    private final static User anonymous = createLocalUser(tr("<anonymous>"));
 
     private static long getNextLocalUid() {
@@ -110,4 +113,8 @@
         }
         return ret;
+    }
+
+    public static User getAnonymous() {
+        return anonymous;
     }
 
@@ -185,5 +192,5 @@
     public static final int STATUS_ANONYMOUS = 4;
 
-    /** 
+    /**
     * Finds out this user's relicensing status and saves it for quicker
     * access.
Index: trunk/src/org/openstreetmap/josm/data/osm/history/History.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/History.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/History.java	(revision 4602)
@@ -156,5 +156,5 @@
                 new FilterPredicate() {
                     public boolean matches(HistoryOsmPrimitive primitive) {
-                        return primitive.getUid() == uid;
+                        return primitive.getUser() != null && primitive.getUser().getId() == uid;
                     }
                 }
Index: trunk/src/org/openstreetmap/josm/data/osm/history/HistoryNode.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/HistoryNode.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/HistoryNode.java	(revision 4602)
@@ -7,4 +7,5 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.User;
 
 /**
@@ -18,6 +19,6 @@
     private LatLon coords;
 
-    public HistoryNode(long id, long version, boolean visible, String user, long uid, long changesetId, Date timestamp, LatLon coords) {
-        super(id, version, visible, user, uid, changesetId, timestamp);
+    public HistoryNode(long id, long version, boolean visible, User user, long changesetId, Date timestamp, LatLon coords) {
+        super(id, version, visible, user, changesetId, timestamp);
         setCoords(coords);
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/history/HistoryOsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/HistoryOsmPrimitive.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/HistoryOsmPrimitive.java	(revision 4602)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 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.tools.CheckParameterUtil;
@@ -29,6 +30,5 @@
     private long id;
     private boolean visible;
-    private String user;
-    private long uid;
+    private User user;
     private long changesetId;
     private Date timestamp;
@@ -54,10 +54,7 @@
      * @throws IllegalArgumentException thrown if preconditions are violated
      */
-    public HistoryOsmPrimitive(long id, long version, boolean visible, String user, long uid, long changesetId, Date timestamp) throws IllegalArgumentException {
+    public HistoryOsmPrimitive(long id, long version, boolean visible, User user, long changesetId, Date timestamp) throws IllegalArgumentException {
         ensurePositiveLong(id, "id");
         ensurePositiveLong(version, "version");
-        if(uid != -1) {
-            ensurePositiveLong(uid, "uid");
-        }
         CheckParameterUtil.ensureParameterNotNull(user, "user");
         CheckParameterUtil.ensureParameterNotNull(timestamp, "timestamp");
@@ -66,5 +63,4 @@
         this.visible = visible;
         this.user = user;
-        this.uid = uid;
         // FIXME: restrict to IDs > 0 as soon as OsmPrimitive holds the
         // changeset id too
@@ -76,6 +72,5 @@
     public HistoryOsmPrimitive(OsmPrimitive p) {
         this(p.getId(), p.getVersion(), p.isVisible(),
-                p.getUser() == null ? null : p.getUser().getName(),
-                p.getUser() == null ? 0 : p.getUser().getId(),
+                p.getUser(),
                 p.getChangesetId(), p.getTimestamp());
     }
@@ -104,9 +99,6 @@
         return visible;
     }
-    public String getUser() {
+    public User getUser() {
         return user;
-    }
-    public long getUid() {
-        return uid;
     }
     public long getChangesetId() {
Index: trunk/src/org/openstreetmap/josm/data/osm/history/HistoryRelation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/HistoryRelation.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/HistoryRelation.java	(revision 4602)
@@ -10,4 +10,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
@@ -34,7 +35,7 @@
      * @throws IllegalArgumentException thrown if preconditions are violated
      */
-    public HistoryRelation(long id, long version, boolean visible, String user, long uid, long changesetId,
+    public HistoryRelation(long id, long version, boolean visible, User user, long changesetId,
             Date timestamp) throws IllegalArgumentException {
-        super(id, version, visible, user, uid, changesetId, timestamp);
+        super(id, version, visible, user, changesetId, timestamp);
     }
     /**
@@ -52,7 +53,7 @@
      * @throws IllegalArgumentException thrown if preconditions are violated
      */
-    public HistoryRelation(long id, long version, boolean visible, String user, long uid, long changesetId,
+    public HistoryRelation(long id, long version, boolean visible, User user, long changesetId,
             Date timestamp, ArrayList<RelationMember> members) {
-        this(id, version, visible, user, uid, changesetId, timestamp);
+        this(id, version, visible, user, changesetId, timestamp);
         if (members != null) {
             this.members.addAll(members);
Index: trunk/src/org/openstreetmap/josm/data/osm/history/HistoryWay.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/HistoryWay.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/HistoryWay.java	(revision 4602)
@@ -10,5 +10,7 @@
 
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
+
 /**
  * Represents an immutable OSM way in the context of a historical view on
@@ -20,10 +22,10 @@
     private ArrayList<Long> nodeIds = new ArrayList<Long>();
 
-    public HistoryWay(long id, long version, boolean visible, String user, long uid, long changesetId, Date timestamp) {
-        super(id, version, visible, user, uid, changesetId, timestamp);
+    public HistoryWay(long id, long version, boolean visible, User user, long changesetId, Date timestamp) {
+        super(id, version, visible, user, changesetId, timestamp);
     }
 
-    public HistoryWay(long id, long version, boolean visible, String user, long uid, long changesetId, Date timestamp, ArrayList<Long> nodeIdList) {
-        this(id, version, visible, user, uid, changesetId, timestamp);
+    public HistoryWay(long id, long version, boolean visible, User user, long changesetId, Date timestamp, ArrayList<Long> nodeIdList) {
+        this(id, version, visible, user, changesetId, timestamp);
         this.nodeIds.addAll(nodeIdList);
     }
Index: trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 4602)
@@ -41,4 +41,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.io.XmlWriter;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Diff;
@@ -420,14 +421,14 @@
             case 2:
                 return isCurrentPointInTime(row);
-            case 3:
-                long uId = getPrimitive(row).getUid();
-                User user = User.getById(uId);
-                int status;
-                if (user == null) {
-                    status = User.STATUS_UNKNOWN;
-                } else {
-                    status = user.getRelicensingStatus();
+            case 3: {
+                    User user = getPrimitive(row).getUser();
+                    int status;
+                    if (user == null) {
+                        status = User.STATUS_UNKNOWN;
+                    } else {
+                        status = user.getRelicensingStatus();
+                    }
+                    return UserListDialog.getRelicensingStatusIcon(status);
                 }
-                return UserListDialog.getRelicensingStatusIcon(status);
             case 4: {
                     HistoryOsmPrimitive p = getPrimitive(row);
@@ -438,6 +439,9 @@
             case 5: {
                     HistoryOsmPrimitive p = getPrimitive(row);
-                    if (p != null)
-                        return "<html>"+p.getUser() + " <font color=gray>(" + p.getUid() + ")</font></html>";
+                    if (p != null) {
+                        User user = p.getUser();
+                        if (user != null)
+                            return "<html>" + XmlWriter.encode(user.getName()) + " <font color=gray>(" + user.getId() + ")</font></html>";
+                    }
                     return null;
                 }
@@ -868,19 +872,11 @@
         private HistoryOsmPrimitive clone;
 
-        private String getUserName(OsmPrimitive primitive) {
-            return primitive.getUser() == null?null:primitive.getUser().getName();
-        }
-
-        private long getUserId(OsmPrimitive primitive) {
-            return primitive.getUser() == null?0:primitive.getUser().getId();
-        }
-
         public void visit(Node n) {
-            clone = new HistoryNode(n.getId(), n.getVersion(), n.isVisible(), getUserName(n), getUserId(n), 0, n.getTimestamp(), n.getCoor());
+            clone = new HistoryNode(n.getId(), n.getVersion(), n.isVisible(), n.getUser(), 0, n.getTimestamp(), n.getCoor());
             clone.setTags(n.getKeys());
         }
 
         public void visit(Relation r) {
-            clone = new HistoryRelation(r.getId(), r.getVersion(), r.isVisible(), getUserName(r), getUserId(r), 0, r.getTimestamp());
+            clone = new HistoryRelation(r.getId(), r.getVersion(), r.isVisible(), r.getUser(), 0, r.getTimestamp());
             clone.setTags(r.getKeys());
             HistoryRelation hr = (HistoryRelation)clone;
@@ -891,5 +887,5 @@
 
         public void visit(Way w) {
-            clone = new HistoryWay(w.getId(), w.getVersion(), w.isVisible(), getUserName(w), getUserId(w), 0, w.getTimestamp());
+            clone = new HistoryWay(w.getId(), w.getVersion(), w.isVisible(), w.getUser(), 0, w.getTimestamp());
             clone.setTags(w.getKeys());
             for (Node n: w.getNodes()) {
Index: trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java	(revision 4602)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AbstractInfoAction;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
 import org.openstreetmap.josm.gui.JMultilineLabel;
@@ -135,6 +136,6 @@
 
             try {
-                if (getPrimitive().getUid() != -1) {
-                    url = AbstractInfoAction.getBaseUserUrl() + "/" +  URLEncoder.encode(getPrimitive().getUser(), "UTF-8").replaceAll("\\+", "%20");
+                if (getPrimitive().getUser() != null && getPrimitive().getUser() != User.getAnonymous()) {
+                    url = AbstractInfoAction.getBaseUserUrl() + "/" +  URLEncoder.encode(getPrimitive().getUser().getName(), "UTF-8").replaceAll("\\+", "%20");
                     lblUser.setUrl(url);
                 } else {
@@ -145,5 +146,8 @@
                 lblUser.setUrl(null);
             }
-            String username = getPrimitive().getUser();
+            String username = "";
+            if (getPrimitive().getUser() != null) {
+                username = getPrimitive().getUser().getName();
+            }
             lblUser.setDescription(username);
         } else {
Index: trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java	(revision 4602)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.data.osm.ChangesetDataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType;
 import org.openstreetmap.josm.data.osm.history.HistoryNode;
@@ -85,9 +86,9 @@
         }
 
-        protected long getAttributeLong(Attributes attr, String name, long defaultValue) throws SAXException{
+        protected Long getAttributeLong(Attributes attr, String name) throws SAXException{
             String v = attr.getValue(name);
             if (v == null)
-                return defaultValue;
-            Long l = 0l;
+                return null;
+            Long l = null;
             try {
                 l = Long.parseLong(v);
@@ -123,11 +124,4 @@
         }
 
-        protected String getAttributeString(Attributes attr, String name, String defaultValue) {
-            String v = attr.getValue(name);
-            if (v == null)
-                return defaultValue;
-            return v;
-        }
-
         protected boolean getMandatoryAttributeBoolean(Attributes attr, String name) throws SAXException{
             String v = attr.getValue(name);
@@ -147,6 +141,18 @@
             long changesetId = getMandatoryAttributeLong(atts,"changeset");
             boolean visible= getMandatoryAttributeBoolean(atts, "visible");
-            long uid = getAttributeLong(atts, "uid",-1);
-            String user = getAttributeString(atts, "user", tr("<anonymous>"));
+            
+            Long uid = getAttributeLong(atts, "uid");
+            String userStr = atts.getValue("user");
+            User user;
+            if (userStr != null) {
+                if (uid != null) {
+                    user = User.createOsmUser(uid, userStr);
+                } else {
+                    user = User.createLocalUser(userStr);
+                }
+            } else {
+                user = User.getAnonymous();
+            }
+
             String v = getMandatoryAttributeString(atts, "timestamp");
             Date timestamp = DateUtils.fromString(v);
@@ -156,14 +162,14 @@
                 double lon = getMandatoryAttributeDouble(atts, "lon");
                 primitive = new HistoryNode(
-                        id,version,visible,user,uid,changesetId,timestamp, new LatLon(lat,lon)
+                        id,version,visible,user,changesetId,timestamp, new LatLon(lat,lon)
                 );
 
             } else if (type.equals(OsmPrimitiveType.WAY)) {
                 primitive = new HistoryWay(
-                        id,version,visible,user,uid,changesetId,timestamp
+                        id,version,visible,user,changesetId,timestamp
                 );
             }if (type.equals(OsmPrimitiveType.RELATION)) {
                 primitive = new HistoryRelation(
-                        id,version,visible,user,uid,changesetId,timestamp
+                        id,version,visible,user,changesetId,timestamp
                 );
             }
Index: trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java	(revision 4601)
+++ trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java	(revision 4602)
@@ -14,4 +14,5 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
 import org.openstreetmap.josm.data.osm.history.HistoryNode;
@@ -81,9 +82,9 @@
         }
 
-        protected long getAttributeLong(Attributes attr, String name, long defaultValue) throws SAXException{
+        protected Long getAttributeLong(Attributes attr, String name) throws SAXException {
             String v = attr.getValue(name);
             if (v == null)
-                return defaultValue;
-            Long l = 0l;
+                return null;
+            Long l = null;
             try {
                 l = Long.parseLong(v);
@@ -116,11 +117,4 @@
                 throwException(tr("Missing mandatory attribute ''{0}''.", name));
             }
-            return v;
-        }
-
-        protected String getAttributeString(Attributes attr, String name, String defaultValue) {
-            String v = attr.getValue(name);
-            if (v == null)
-                return defaultValue;
             return v;
         }
@@ -143,6 +137,16 @@
             long changesetId = getMandatoryAttributeLong(atts,"changeset");
             boolean visible= getMandatoryAttributeBoolean(atts, "visible");
-            long uid = getAttributeLong(atts, "uid",-1);
-            String user = getAttributeString(atts, "user", tr("<anonymous>"));
+            Long uid = getAttributeLong(atts, "uid");
+            String userStr = atts.getValue("user");
+            User user;
+            if (userStr != null) {
+                if (uid != null) {
+                    user = User.createOsmUser(uid, userStr);
+                } else {
+                    user = User.createLocalUser(userStr);
+                }
+            } else {
+                user = User.getAnonymous();
+            }
             String v = getMandatoryAttributeString(atts, "timestamp");
             Date timestamp = DateUtils.fromString(v);
@@ -152,14 +156,14 @@
                 double lon = getMandatoryAttributeDouble(atts, "lon");
                 primitive = new HistoryNode(
-                        id,version,visible,user,uid,changesetId,timestamp, new LatLon(lat,lon)
+                        id,version,visible,user,changesetId,timestamp, new LatLon(lat,lon)
                 );
 
             } else if (type.equals(OsmPrimitiveType.WAY)) {
                 primitive = new HistoryWay(
-                        id,version,visible,user,uid,changesetId,timestamp
+                        id,version,visible,user,changesetId,timestamp
                 );
             }if (type.equals(OsmPrimitiveType.RELATION)) {
                 primitive = new HistoryRelation(
-                        id,version,visible,user,uid,changesetId,timestamp
+                        id,version,visible,user,changesetId,timestamp
                 );
             }
