Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmChangeTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmChangeTask.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmChangeTask.java	(revision 4734)
@@ -1,6 +1,8 @@
 package org.openstreetmap.josm.actions.downloadtasks;
 
-import static org.openstreetmap.josm.tools.I18n.tr;
-
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
 import java.util.concurrent.Future;
 
@@ -8,9 +10,23 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.gui.io.UpdatePrimitivesTask;
+import org.openstreetmap.josm.data.osm.NodeData;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.PrimitiveData;
+import org.openstreetmap.josm.data.osm.PrimitiveId;
+import org.openstreetmap.josm.data.osm.RelationData;
+import org.openstreetmap.josm.data.osm.WayData;
+import org.openstreetmap.josm.data.osm.history.History;
+import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
+import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
+import org.openstreetmap.josm.data.osm.history.HistoryNode;
+import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
+import org.openstreetmap.josm.data.osm.history.HistoryRelation;
+import org.openstreetmap.josm.data.osm.history.HistoryWay;
+import org.openstreetmap.josm.gui.history.HistoryLoadTask;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.OsmServerLocationReader;
 import org.openstreetmap.josm.io.OsmServerReader;
 import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.tools.Pair;
 
 public class DownloadOsmChangeTask extends DownloadOsmTask {
@@ -65,7 +81,96 @@
             if (isFailed() || isCanceled() || downloadedData == null)
                 return; // user canceled download or error occurred
-            progressMonitor.subTask(tr("Updating data"));
-            UpdatePrimitivesTask task = new UpdatePrimitivesTask(targetLayer, downloadedData.allPrimitives());
-            Main.worker.submit(task);
+            try {
+                // A changeset does not contain all referred primitives, this is the list of incomplete ones
+                List<OsmPrimitive> toLoad = new ArrayList<OsmPrimitive>();
+                // For each incomplete primitive, we'll have to get its state at date it was referred
+                List<Pair<OsmPrimitive, Date>> toMonitor = new ArrayList<Pair<OsmPrimitive, Date>>();
+                for (OsmPrimitive p : downloadedData.allNonDeletedPrimitives()) {
+                    if (p.isIncomplete()) {
+                        Date timestamp = null;
+                        for (OsmPrimitive ref : p.getReferrers()) {
+                            if (!ref.isTimestampEmpty()) {
+                                timestamp = ref.getTimestamp();
+                                break;
+                            }
+                        }
+                        toLoad.add(p);
+                        toMonitor.add(new Pair<OsmPrimitive, Date>(p, timestamp));
+                    }
+                }
+                if (isCanceled()) return;
+                // Updating process is asynchronous and done after each history request
+                HistoryDataSet.getInstance().addHistoryDataSetListener(new HistoryListener(toMonitor));
+                // Let's load all required history
+                Main.worker.submit(new HistoryLoadTask().add(toLoad));
+            } catch (Exception e) {
+                rememberException(e);
+                setFailed(true);
+            }
+        }
+    }
+    /**
+     * Asynchroneous updater of incomplete primitives.
+     *
+     */
+    private class HistoryListener implements HistoryDataSetListener {
+
+        private final List<Pair<OsmPrimitive, Date>> toMonitor;
+        
+        public HistoryListener(List<Pair<OsmPrimitive, Date>> toMonitor) {
+            this.toMonitor = toMonitor;
+        }
+
+        @Override
+        public void historyUpdated(HistoryDataSet source, PrimitiveId id) {
+            for (Iterator<Pair<OsmPrimitive, Date>> it = toMonitor.iterator(); it.hasNext();) {
+                Pair<OsmPrimitive, Date> pair = it.next();
+                History history = source.getHistory(pair.a.getPrimitiveId());
+                // If the history has been loaded and a timestamp is known
+                if (history != null && pair.b != null) {
+                    // Lookup for the primitive version at the specified timestamp
+                    HistoryOsmPrimitive hp = history.getByDate(pair.b);
+                    if (hp != null) {
+                        PrimitiveData data = null;
+                        
+                        switch (pair.a.getType()) {
+                            case NODE:
+                                data = new NodeData();
+                                ((NodeData)data).setCoor(((HistoryNode)hp).getCoords());
+                                break;
+                            case WAY: 
+                                data = new WayData();
+                                ((WayData)data).setNodes(((HistoryWay)hp).getNodes());
+                                break;
+                            case RELATION: 
+                                data = new RelationData();
+                                ((RelationData)data).setMembers(((HistoryRelation)hp).getMembers());
+                                break;
+                            default: throw new AssertionError();
+                        }
+                        
+                        data.setUser(hp.getUser());
+                        data.setVisible(hp.isVisible());
+                        data.setTimestamp(hp.getTimestamp());
+                        data.setKeys(hp.getTags());
+                        data.setOsmId(hp.getChangesetId(), (int) hp.getVersion());
+                        
+                        // Load the history data
+                        pair.a.load(data);
+                        // Forget this primitive
+                        it.remove();
+                    }
+                }
+            }
+            if (toMonitor.isEmpty()) {
+                // No more primitive to update. Processing is finished
+                source.removeHistoryDataSetListener(this);
+                // Be sure all updated primitives are correctly drawn
+                Main.map.repaint();
+            }
+        }
+
+        @Override
+        public void historyDataSetCleared(HistoryDataSet source) {
         }
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/history/HistoryRelation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/HistoryRelation.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/HistoryRelation.java	(revision 4734)
@@ -10,4 +10,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMemberData;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -20,5 +21,5 @@
 public class HistoryRelation extends HistoryOsmPrimitive{
 
-    private ArrayList<RelationMember> members = new ArrayList<RelationMember>();
+    private ArrayList<RelationMemberData> members = new ArrayList<RelationMemberData>();
 
     /**
@@ -54,5 +55,5 @@
      */
     public HistoryRelation(long id, long version, boolean visible, User user, long changesetId,
-            Date timestamp, ArrayList<RelationMember> members) {
+            Date timestamp, ArrayList<RelationMemberData> members) {
         this(id, version, visible, user, changesetId, timestamp);
         if (members != null) {
@@ -70,5 +71,5 @@
      * @return an immutable list of members of this relation
      */
-    public List<RelationMember> getMembers() {
+    public List<RelationMemberData> getMembers() {
         return Collections.unmodifiableList(members);
     }
@@ -90,5 +91,5 @@
      * @throws IndexOutOfBoundsException thrown, if idx is out of bounds
      */
-    public RelationMember getRelationMember(int idx) throws IndexOutOfBoundsException  {
+    public RelationMemberData getRelationMember(int idx) throws IndexOutOfBoundsException  {
         if (idx < 0 || idx >= members.size())
             throw new IndexOutOfBoundsException(MessageFormat.format("Parameter {0} not in range 0..{1}. Got ''{2}''.", "idx", members.size(),idx));
@@ -111,5 +112,5 @@
      * @exception IllegalArgumentException thrown, if member is null
      */
-    public void addMember(RelationMember member) throws IllegalArgumentException {
+    public void addMember(RelationMemberData member) throws IllegalArgumentException {
         CheckParameterUtil.ensureParameterNotNull(member, "member");
         members.add(member);
Index: trunk/src/org/openstreetmap/josm/data/osm/history/RelationMember.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/RelationMember.java	(revision 4733)
+++ 	(revision )
@@ -1,58 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.osm.history;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
-import org.openstreetmap.josm.tools.CheckParameterUtil;
-
-/**
- * Represents a relation member in the context of a historical view on
- * OSM data.
- *
- */
-public class RelationMember {
-
-    private String role;
-    private OsmPrimitiveType primitiveType;
-    private long primitiveId;
-
-    /**
-     *
-     * @param role  the role
-     * @param primitiveType  the type (must not be null)
-     * @param primitiveId the id
-     *
-     * @exception IllegalArgumentException thrown, if primitiveType is null
-     */
-    public RelationMember(String role, OsmPrimitiveType primitiveType, long primitiveId) {
-        this.role = (role == null ? "" : role);
-        CheckParameterUtil.ensureParameterNotNull(primitiveType, "primitiveType");
-        this.primitiveType = primitiveType;
-        this.primitiveId = primitiveId;
-    }
-
-    /**
-     * replies the member role
-     * @return the member role
-     */
-    public String getRole() {
-        return role;
-    }
-
-    /**
-     * replies the type of the referenced OSM primitive
-     *
-     * @return the type of the referenced OSM primitive
-     */
-    public OsmPrimitiveType getPrimitiveType() {
-        return primitiveType;
-    }
-
-    /**
-     * replies the id of the referenced OSM primitive
-     *
-     * @return the id of the referenced OSM primitive
-     */
-    public long getPrimitiveId() {
-        return primitiveId;
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 4734)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.RelationMemberData;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
@@ -42,5 +43,4 @@
 import org.openstreetmap.josm.io.XmlWriter;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.Diff;
 
 /**
@@ -721,5 +721,5 @@
                 return false;
             return
-            thisRelation.getMembers().get(row).getPrimitiveId() == oppositeRelation.getMembers().get(row).getPrimitiveId()
+            thisRelation.getMembers().get(row).getMemberId() == oppositeRelation.getMembers().get(row).getMemberId()
             &&  thisRelation.getMembers().get(row).getRole().equals(oppositeRelation.getMembers().get(row).getRole());
         }
@@ -881,5 +881,5 @@
             HistoryRelation hr = (HistoryRelation)clone;
             for (RelationMember rm : r.getMembers()) {
-                hr.addMember(new org.openstreetmap.josm.data.osm.history.RelationMember(rm.getRole(), rm.getType(), rm.getUniqueId()));
+                hr.addMember(new RelationMemberData(rm.getRole(), rm.getType(), rm.getUniqueId()));
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/history/RelationMemberListTableCellRenderer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/RelationMemberListTableCellRenderer.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/gui/history/RelationMemberListTableCellRenderer.java	(revision 4734)
@@ -14,5 +14,5 @@
 
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
-import org.openstreetmap.josm.data.osm.history.RelationMember;
+import org.openstreetmap.josm.data.osm.RelationMemberData;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -39,13 +39,13 @@
     }
 
-    protected void renderIcon(RelationMember member) {
+    protected void renderIcon(RelationMemberData member) {
         if (member == null) {
             setIcon(null);
         } else {
-            setIcon(icons.get(member.getPrimitiveType()));
+            setIcon(icons.get(member.getMemberType()));
         }
     }
 
-    protected void renderRole( HistoryBrowserModel.RelationMemberTableModel model, RelationMember member, int row, boolean isSelected) {
+    protected void renderRole( HistoryBrowserModel.RelationMemberTableModel model, RelationMemberData member, int row, boolean isSelected) {
         String text = "";
         Color bgColor = Color.WHITE;
@@ -67,5 +67,5 @@
     }
 
-    protected void renderPrimitive( HistoryBrowserModel.RelationMemberTableModel model, RelationMember member, int row, boolean isSelected) {
+    protected void renderPrimitive( HistoryBrowserModel.RelationMemberTableModel model, RelationMemberData member, int row, boolean isSelected) {
         String text = "";
         Color bgColor = Color.WHITE;
@@ -74,8 +74,8 @@
         } else {
             text = "";
-            switch(member.getPrimitiveType()) {
-            case NODE: text = tr("Node {0}", member.getPrimitiveId()); break;
-            case WAY: text = tr("Way {0}", member.getPrimitiveId()); break;
-            case RELATION: text = tr("Relation {0}", member.getPrimitiveId()); break;
+            switch(member.getMemberType()) {
+            case NODE: text = tr("Node {0}", member.getMemberId()); break;
+            case WAY: text = tr("Way {0}", member.getMemberId()); break;
+            case RELATION: text = tr("Relation {0}", member.getMemberId()); break;
             }
             if (model.isSameInOppositeWay(row)) {
@@ -97,5 +97,5 @@
 
         HistoryBrowserModel.RelationMemberTableModel model = gteRelationMemberTableModel(table);
-        RelationMember member = (RelationMember)value;
+        RelationMemberData member = (RelationMemberData)value;
         renderIcon(member);
         switch(column) {
Index: trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java	(revision 4734)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.data.osm.ChangesetDataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.RelationMemberData;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType;
@@ -209,5 +210,5 @@
             }
             String role = getMandatoryAttributeString(atts, "role");
-            org.openstreetmap.josm.data.osm.history.RelationMember member = new org.openstreetmap.josm.data.osm.history.RelationMember(role, type,ref);
+            RelationMemberData member = new RelationMemberData(role, type,ref);
             ((HistoryRelation)currentPrimitive).addMember(member);
         }
Index: trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/io/OsmHistoryReader.java	(revision 4734)
@@ -14,4 +14,5 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.RelationMemberData;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
@@ -203,5 +204,5 @@
             }
             String role = getMandatoryAttributeString(atts, "role");
-            org.openstreetmap.josm.data.osm.history.RelationMember member = new org.openstreetmap.josm.data.osm.history.RelationMember(role, type,ref);
+            RelationMemberData member = new RelationMemberData(role, type,ref);
             ((HistoryRelation)current).addMember(member);
         }
Index: trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java	(revision 4733)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java	(revision 4734)
@@ -22,4 +22,7 @@
  * It can either download the object including or not including its immediate children.
  * The former case is called a "full download".
+ * 
+ * It can also download a specific version of the object (however, "full" download is not possible
+ * in that case).
  *
  */
@@ -29,4 +32,6 @@
     /** true if a full download is required, i.e. a download including the immediate children */
     private boolean full;
+    /** the specific version number, if required (incompatible with full), or -1 else */
+    private int version;
 
     /**
@@ -41,4 +46,21 @@
      */
     public OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full) throws IllegalArgumentException {
+        this(id, type, full, -1);
+    }
+
+    /**
+     * Creates a new server object reader for a given id and a primitive type.
+     *
+     * @param id the object id. > 0 required.
+     * @param type the type. Must not be null.
+     * @param version the specific version number, if required; -1, otherwise
+     * @throws IllegalArgumentException thrown if id <= 0
+     * @throws IllegalArgumentException thrown if type is null
+     */
+    public OsmServerObjectReader(long id, OsmPrimitiveType type, int version) throws IllegalArgumentException {
+        this(id, type, false, version);
+    }
+
+    protected OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full, int version) throws IllegalArgumentException {
         if (id <= 0)
             throw new IllegalArgumentException(MessageFormat.format("Expected value > 0 for parameter ''{0}'', got {1}", "id", id));
@@ -46,4 +68,5 @@
         this.id = new SimplePrimitiveId(id, type);
         this.full = full;
+        this.version = version;
     }
 
@@ -58,7 +81,24 @@
      */
     public OsmServerObjectReader(PrimitiveId id, boolean full) {
+        this(id, full, -1);
+    }
+
+    /**
+     * Creates a new server object reader for an object with the given <code>id</code>
+     *
+     * @param id the object id. Must not be null. Unique id > 0 required.
+     * @param version the specific version number, if required; -1, otherwise
+     * @throws IllegalArgumentException thrown if id is null
+     * @throws IllegalArgumentException thrown if id.getUniqueId() <= 0
+     */
+    public OsmServerObjectReader(PrimitiveId id, int version) {
+        this(id, false, version);
+    }
+
+    protected OsmServerObjectReader(PrimitiveId id, boolean full, int version) {
         CheckParameterUtil.ensureValidPrimitiveId(id, "id");
         this.id = id;
         this.full = full;
+        this.version = version;
     }
 
@@ -87,4 +127,6 @@
             if (full && ! id.getType().equals(OsmPrimitiveType.NODE)) {
                 sb.append("/full");
+            } else if (version > 0) {
+                sb.append("/"+version);
             }
 
