Index: trunk/src/org/openstreetmap/josm/data/osm/NoteData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/NoteData.java	(revision 7698)
+++ trunk/src/org/openstreetmap/josm/data/osm/NoteData.java	(revision 7699)
@@ -5,4 +5,5 @@
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import org.openstreetmap.josm.Main;
@@ -59,6 +60,27 @@
     public void setSelectedNote(Note note) {
         selectedNote = note;
-        Main.map.noteDialog.selectionChanged();
-        Main.map.mapView.repaint();
+        if (Main.map != null) {
+            Main.map.noteDialog.selectionChanged();
+            Main.map.mapView.repaint();
+        }
+    }
+
+    /**
+     * Return whether or not there are any changes in the note data set.
+     * These changes may need to be either uploaded or saved.
+     * @return true if local modifications have been made to the note data set. False otherwise.
+     */
+    public synchronized boolean isModified() {
+        for (Note note : noteList) {
+            if (note.getId() < 0) { //notes with negative IDs are new
+                return true;
+            }
+            for (NoteComment comment : note.getComments()) {
+                if (comment.getIsNew()) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
@@ -67,5 +89,5 @@
      * @param newNotes A list of notes to add
      */
-    public void addNotes(List<Note> newNotes) {
+    public synchronized void addNotes(List<Note> newNotes) {
         for (Note newNote : newNotes) {
             if (!noteList.contains(newNote)) {
@@ -77,5 +99,7 @@
         }
         dataUpdated();
-        Main.debug("notes in current set: " + noteList.size());
+        if (Main.isDebugEnabled()) {
+            Main.debug("notes in current set: " + noteList.size());
+        }
     }
 
@@ -85,5 +109,5 @@
      * @param text Required comment with which to open the note
      */
-    public void createNote(LatLon location, String text) {
+    public synchronized void createNote(LatLon location, String text) {
         if(text == null || text.isEmpty()) {
             throw new IllegalArgumentException("Comment can not be blank when creating a note");
@@ -95,5 +119,7 @@
         NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.opened, true);
         note.addComment(comment);
-        Main.debug("Created note {0} with comment: {1}", note.getId(), text);
+        if (Main.isDebugEnabled()) {
+            Main.debug("Created note {0} with comment: {1}", note.getId(), text);
+        }
         noteList.add(note);
         dataUpdated();
@@ -105,5 +131,5 @@
      * @param text Comment to add
      */
-    public void addCommentToNote(Note note, String text) {
+    public synchronized void addCommentToNote(Note note, String text) {
         if (!noteList.contains(note)) {
             throw new IllegalArgumentException("Note to modify must be in layer");
@@ -112,5 +138,7 @@
             throw new IllegalStateException("Cannot add a comment to a closed note");
         }
-        Main.debug("Adding comment to note {0}: {1}", note.getId(), text);
+        if (Main.isDebugEnabled()) {
+            Main.debug("Adding comment to note {0}: {1}", note.getId(), text);
+        }
         NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.commented, true);
         note.addComment(comment);
@@ -123,5 +151,5 @@
      * @param text Comment to attach to close action, if desired
      */
-    public void closeNote(Note note, String text) {
+    public synchronized void closeNote(Note note, String text) {
         if (!noteList.contains(note)) {
             throw new IllegalArgumentException("Note to close must be in layer");
@@ -130,5 +158,7 @@
             throw new IllegalStateException("Cannot close a note that isn't open");
         }
-        Main.debug("closing note {0} with comment: {1}", note.getId(), text);
+        if (Main.isDebugEnabled()) {
+            Main.debug("closing note {0} with comment: {1}", note.getId(), text);
+        }
         NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.closed, true);
         note.addComment(comment);
@@ -143,5 +173,5 @@
      * @param text Comment to attach to the reopen action, if desired
      */
-    public void reOpenNote(Note note, String text) {
+    public synchronized void reOpenNote(Note note, String text) {
         if (!noteList.contains(note)) {
             throw new IllegalArgumentException("Note to reopen must be in layer");
@@ -150,5 +180,7 @@
             throw new IllegalStateException("Cannot reopen a note that isn't closed");
         }
-        Main.debug("reopening note {0} with comment: {1}", note.getId(), text);
+        if (Main.isDebugEnabled()) {
+            Main.debug("reopening note {0} with comment: {1}", note.getId(), text);
+        }
         NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.reopened, true);
         note.addComment(comment);
@@ -166,3 +198,17 @@
         return User.createOsmUser(userMgr.getUserId(), userMgr.getUserName());
     }
+
+    /**
+     * Updates notes with new state. Primarily to be used when updating the
+     * note layer after uploading note changes to the server.
+     * @param updatedNotes Map containing the original note as the key and the updated note as the value
+     */
+    public synchronized void updateNotes(Map<Note, Note> updatedNotes) {
+        for (Map.Entry<Note, Note> entry : updatedNotes.entrySet()) {
+            Note oldNote = entry.getKey();
+            Note newNote = entry.getValue();
+            oldNote.updateWith(newNote);
+        }
+        dataUpdated();
+    }
 }
