Index: /trunk/src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UploadAction.java	(revision 2978)
+++ /trunk/src/org/openstreetmap/josm/actions/UploadAction.java	(revision 2979)
@@ -18,4 +18,6 @@
 import org.openstreetmap.josm.data.APIDataSet;
 import org.openstreetmap.josm.data.conflict.ConflictCollection;
+import org.openstreetmap.josm.gui.HelpAwareOptionPane;
+import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.io.UploadDialog;
 import org.openstreetmap.josm.gui.io.UploadPrimitivesTask;
@@ -101,18 +103,34 @@
     }
 
+    protected void alertUnresolvedConflicts(OsmDataLayer layer) {
+        HelpAwareOptionPane.showOptionDialog(
+                Main.parent,
+                tr("<html>The data to be uploaded participates in unresolved conflicts of layer ''{0}''.<br>"
+                        + "You have to resolve them first.</html>", layer.getName()
+                ),
+                tr("Warning"),
+                JOptionPane.WARNING_MESSAGE,
+                HelpUtil.ht("/Action/Upload#PrimitivesParticipateInConflicts")
+        );
+    }
+
+    /**
+     * Check whether the preconditions are met to upload data in <code>apiData</code>.
+     * Makes sure primitives in <code>apiData</code> don't participate in conflicts and
+     * runs the installed {@see UploadHook}s.
+     * 
+     * @param layer the source layer of the data to be uploaded
+     * @param apiData the data to be uploaded
+     * @return true, if the preconditions are met; false, otherwise
+     */
     public boolean checkPreUploadConditions(OsmDataLayer layer, APIDataSet apiData) {
         ConflictCollection conflicts = layer.getConflicts();
-        if (conflicts !=null && !conflicts.isEmpty()) {
-            JOptionPane.showMessageDialog(
-                    Main.parent,
-                    tr("<html>There are unresolved conflicts in layer ''{0}''.<br>"
-                            + "You have to resolve them first.</html>", layer.getName()),
-                            tr("Warning"),
-                            JOptionPane.WARNING_MESSAGE
-            );
+        if (apiData.participatesInConflict(conflicts)) {
+            alertUnresolvedConflicts(layer);
             return false;
         }
-        // Call all upload hooks in sequence. The upload confirmation dialog
-        // is one of these.
+        // Call all upload hooks in sequence.
+        // FIXME: this should become an asynchronous task
+        //
         for(UploadHook hook : uploadHooks)
             if(!hook.checkUpload(apiData))
@@ -122,4 +140,10 @@
     }
 
+    /**
+     * Uploads data to the OSM API.
+     * 
+     * @param layer the source layer for the data to upload
+     * @param apiData the primitives to be added, updated, or deleted
+     */
     public void uploadData(OsmDataLayer layer, APIDataSet apiData) {
         if (apiData.isEmpty()) {
Index: /trunk/src/org/openstreetmap/josm/actions/UploadSelectionAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(revision 2978)
+++ /trunk/src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(revision 2979)
@@ -133,4 +133,12 @@
     }
 
+    /**
+     * Replies true if there is at least one non-new, deleted primitive in
+     * <code>primitives</code>
+     * 
+     * @param primitives the primitives to scan
+     * @return true if there is at least one non-new, deleted primitive in
+     * <code>primitives</code>
+     */
     protected boolean hasPrimitivesToDelete(Collection<OsmPrimitive> primitives) {
         for (OsmPrimitive p: primitives)
@@ -139,4 +147,5 @@
         return false;
     }
+
     /**
      * Uploads the primitives in <code>toUpload</code> to the server. Only
Index: /trunk/src/org/openstreetmap/josm/data/APIDataSet.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/APIDataSet.java	(revision 2978)
+++ /trunk/src/org/openstreetmap/josm/data/APIDataSet.java	(revision 2979)
@@ -15,7 +15,10 @@
 
 import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException;
+import org.openstreetmap.josm.data.conflict.Conflict;
+import org.openstreetmap.josm.data.conflict.ConflictCollection;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.PrimitiveId;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
@@ -137,4 +140,49 @@
         this();
         init(ds);
+    }
+
+    /**
+     * Replies true if one of the primitives to be updated or to be deleted
+     * participates in the conflict <code>conflict</code>
+     * 
+     * @param conflict the conflict
+     * @return true if one of the primitives to be updated or to be deleted
+     * participates in the conflict <code>conflict</code>
+     */
+    public boolean participatesInConflict(Conflict<?> conflict) {
+        if (conflict == null) return false;
+        for (OsmPrimitive p: toUpdate) {
+            if (conflict.isParticipating(p)) return true;
+        }
+        for (OsmPrimitive p: toDelete) {
+            if (conflict.isParticipating(p)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Replies true if one of the primitives to be updated or to be deleted
+     * participates in at least one conflict in <code>conflicts</code>
+     * 
+     * @param conflicts the collection of conflicts
+     * @return true if one of the primitives to be updated or to be deleted
+     * participates in at least one conflict in <code>conflicts</code>
+     */
+    public boolean participatesInConflict(ConflictCollection conflicts) {
+        if (conflicts == null || conflicts.isEmpty()) return false;
+        Set<PrimitiveId> idsParticipatingInConflicts = new HashSet<PrimitiveId>();
+        for (OsmPrimitive p: conflicts.getMyConflictParties()) {
+            idsParticipatingInConflicts.add(p.getPrimitiveId());
+        }
+        for (OsmPrimitive p: conflicts.getTheirConflictParties()) {
+            idsParticipatingInConflicts.add(p.getPrimitiveId());
+        }
+        for (OsmPrimitive p: toUpdate) {
+            if (idsParticipatingInConflicts.contains(p.getPrimitiveId())) return true;
+        }
+        for (OsmPrimitive p: toDelete) {
+            if (idsParticipatingInConflicts.contains(p.getPrimitiveId())) return true;
+        }
+        return false;
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/conflict/Conflict.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/conflict/Conflict.java	(revision 2978)
+++ /trunk/src/org/openstreetmap/josm/data/conflict/Conflict.java	(revision 2979)
@@ -3,4 +3,5 @@
 
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.PrimitiveId;
 
 /**
@@ -42,4 +43,32 @@
     }
 
+    /**
+     * Replies true if the primitive <code>primitive</code> is participating
+     * in this conflict
+     * 
+     * @param primitive the primitive
+     * @return true if the primitive <code>primitive</code> is participating
+     * in this conflict
+     */
+    public boolean isParticipating(OsmPrimitive primitive) {
+        if (primitive == null) return false;
+        return primitive.getPrimitiveId().equals(my.getPrimitiveId())
+        || primitive.getPrimitiveId().equals(their.getPrimitiveId());
+    }
+
+    /**
+     * Replies true if the primitive with id <code>id</code> is participating
+     * in this conflict
+     * 
+     * @param id the primitive id
+     * @return true if the primitive <code>primitive</code> is participating
+     * in this conflict
+     */
+    public boolean isParticipating(PrimitiveId id) {
+        if (id == null) return false;
+        return id.equals(my.getPrimitiveId())
+        || id.equals(their.getPrimitiveId());
+    }
+
     @Override
     public int hashCode() {
