Ticket #10700: note_upload.patch
| File note_upload.patch, 13.9 KB (added by , 11 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/UploadNotesAction.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.actions; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.awt.event.ActionEvent; 7 import java.util.List; 8 9 import org.openstreetmap.josm.Main; 10 import org.openstreetmap.josm.actions.upload.UploadNotesTask; 11 import org.openstreetmap.josm.data.osm.NoteData; 12 import org.openstreetmap.josm.gui.layer.NoteLayer; 13 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor; 14 import org.openstreetmap.josm.tools.ImageProvider; 15 16 /** 17 * Action to initiate uploading changed notes to the OSM server. 18 * On click, it finds the note layer and fires off an upload task 19 * with the note data contained in the layer. 20 * 21 */ 22 public class UploadNotesAction extends JosmAction { 23 24 /** Create a new action to upload notes */ 25 public UploadNotesAction () { 26 putValue(SHORT_DESCRIPTION,tr("Upload note changes to server")); 27 putValue(NAME, tr("Upload notes")); 28 putValue(SMALL_ICON, ImageProvider.get("upload")); 29 } 30 31 @Override 32 public void actionPerformed(ActionEvent e) { 33 List<NoteLayer> noteLayers = null; 34 if (Main.map != null) { 35 noteLayers = Main.map.mapView.getLayersOfType(NoteLayer.class); 36 } 37 NoteLayer layer; 38 if (noteLayers != null && noteLayers.size() > 0) { 39 layer = noteLayers.get(0); 40 } else { 41 Main.error("No note layer found"); 42 return; 43 } 44 Main.debug("uploading note changes"); 45 NoteData noteData = layer.getNoteData(); 46 47 if(noteData == null || !noteData.isModified()) { 48 Main.debug("No changed notes to upload"); 49 return; 50 } 51 UploadNotesTask uploadTask = new UploadNotesTask(); 52 uploadTask.uploadNotes(noteData, new PleaseWaitProgressMonitor(tr("Uploading notes to server"))); 53 } 54 } -
src/org/openstreetmap/josm/actions/upload/UploadNotesTask.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.actions.upload; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.io.IOException; 7 import java.util.HashMap; 8 import java.util.Map; 9 10 import javax.swing.JOptionPane; 11 12 import org.openstreetmap.josm.Main; 13 import org.openstreetmap.josm.data.notes.Note; 14 import org.openstreetmap.josm.data.notes.NoteComment; 15 import org.openstreetmap.josm.data.osm.NoteData; 16 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 17 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 18 import org.openstreetmap.josm.io.OsmApi; 19 import org.openstreetmap.josm.io.OsmTransferException; 20 import org.xml.sax.SAXException; 21 22 /** 23 * Class for uploading note changes to the server 24 */ 25 public class UploadNotesTask { 26 27 private UploadTask uploadTask; 28 private NoteData noteData; 29 30 /** 31 * Upload notes with modifications to the server 32 * @param noteData Note dataset with changes to upload 33 * @param progressMonitor progress monitor for user feedback 34 */ 35 public void uploadNotes(NoteData noteData, ProgressMonitor progressMonitor) { 36 this.noteData = noteData; 37 uploadTask = new UploadTask("Uploading modified notes", progressMonitor); 38 Main.worker.submit(uploadTask); 39 } 40 41 private class UploadTask extends PleaseWaitRunnable { 42 43 private boolean isCanceled = false; 44 Map<Note, Note> updatedNotes = new HashMap<>(); 45 Map<Note, Exception> failedNotes = new HashMap<>(); 46 47 public UploadTask(String title, ProgressMonitor monitor) { 48 super(title, monitor, false); 49 } 50 51 @Override 52 protected void cancel() { 53 Main.debug("note upload canceled"); 54 isCanceled = true; 55 } 56 57 @Override 58 protected void realRun() throws SAXException, IOException, OsmTransferException { 59 ProgressMonitor monitor = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false); 60 OsmApi api = OsmApi.getOsmApi(); 61 for (Note note : noteData.getNotes()) { 62 if(isCanceled) { 63 Main.info("Note upload interrupted by user"); 64 break; 65 } 66 for (NoteComment comment : note.getComments()) { 67 if (comment.getIsNew()) { 68 Main.debug("found note change to upload"); 69 try { 70 Note newNote; 71 switch (comment.getNoteAction()) { 72 case opened: 73 Main.debug("opening new note"); 74 newNote = api.createNote(note.getLatLon(), comment.getText(), monitor); 75 note.setId(newNote.getId()); 76 break; 77 case closed: 78 Main.debug("closing note " + note.getId()); 79 newNote = api.closeNote(note, comment.getText(), monitor); 80 break; 81 case commented: 82 Main.debug("adding comment to note " + note.getId()); 83 newNote = api.addCommentToNote(note, comment.getText(), monitor); 84 break; 85 case reopened: 86 Main.debug("reopening note " + note.getId()); 87 newNote = api.reopenNote(note, comment.getText(), monitor); 88 break; 89 default: 90 newNote = null; 91 } 92 updatedNotes.put(note, newNote); 93 } catch (Exception e) { 94 Main.error("Failed to upload note to server: " + note.getId()); 95 failedNotes.put(note, e); 96 } 97 } 98 } 99 } 100 } 101 102 /** Updates the note layer with uploaded notes and notifies the user of any upload failures */ 103 @Override 104 protected void finish() { 105 Main.debug("finish called in notes upload task. Notes to update: " + updatedNotes.size()); 106 noteData.updateNotes(updatedNotes); 107 if (!failedNotes.isEmpty()) { 108 Main.error("Some notes failed to upload"); 109 StringBuilder sb = new StringBuilder(); 110 for (Map.Entry<Note, Exception> entry : failedNotes.entrySet()) { 111 sb.append(tr("Note {0} failed: {1}", entry.getKey().getId(), entry.getValue().getMessage())); 112 sb.append("\n"); 113 } 114 Main.error("Notes failed to upload: " + sb.toString()); 115 JOptionPane.showMessageDialog(Main.map, sb.toString(), tr("Notes failed to upload"), JOptionPane.ERROR_MESSAGE); 116 } 117 } 118 119 } 120 121 } -
src/org/openstreetmap/josm/data/osm/NoteData.java
4 4 import java.util.ArrayList; 5 5 import java.util.Date; 6 6 import java.util.List; 7 import java.util.Map; 7 8 8 9 import org.openstreetmap.josm.Main; 9 10 import org.openstreetmap.josm.data.coor.LatLon; … … 63 64 } 64 65 65 66 /** 67 * Return whether or not there are any changes in the note data set. 68 * These changes may need to be either uploaded or saved. 69 * @return true if local modifications have been made to the note data set. False otherwise. 70 */ 71 public synchronized boolean isModified() { 72 for (Note note : noteList) { 73 if (note.getId() < 0) { //notes with negative IDs are new 74 return true; 75 } 76 for (NoteComment comment : note.getComments()) { 77 if (comment.getIsNew()) { 78 return true; 79 } 80 } 81 } 82 return false; 83 } 84 85 /** 66 86 * Add notes to the data set. It only adds a note if the ID is not already present 67 87 * @param newNotes A list of notes to add 68 88 */ 69 public void addNotes(List<Note> newNotes) {89 public synchronized void addNotes(List<Note> newNotes) { 70 90 for (Note newNote : newNotes) { 71 91 if (!noteList.contains(newNote)) { 72 92 noteList.add(newNote); … … 84 104 * @param location Location of note 85 105 * @param text Required comment with which to open the note 86 106 */ 87 public void createNote(LatLon location, String text) {107 public synchronized void createNote(LatLon location, String text) { 88 108 if(text == null || text.isEmpty()) { 89 109 throw new IllegalArgumentException("Comment can not be blank when creating a note"); 90 110 } … … 104 124 * @param note Note to add comment to. Must already exist in the layer 105 125 * @param text Comment to add 106 126 */ 107 public void addCommentToNote(Note note, String text) {127 public synchronized void addCommentToNote(Note note, String text) { 108 128 if (!noteList.contains(note)) { 109 129 throw new IllegalArgumentException("Note to modify must be in layer"); 110 130 } … … 122 142 * @param note Note to close. Must already exist in the layer 123 143 * @param text Comment to attach to close action, if desired 124 144 */ 125 public void closeNote(Note note, String text) {145 public synchronized void closeNote(Note note, String text) { 126 146 if (!noteList.contains(note)) { 127 147 throw new IllegalArgumentException("Note to close must be in layer"); 128 148 } … … 142 162 * @param note Note to reopen. Must already exist in the layer 143 163 * @param text Comment to attach to the reopen action, if desired 144 164 */ 145 public void reOpenNote(Note note, String text) {165 public synchronized void reOpenNote(Note note, String text) { 146 166 if (!noteList.contains(note)) { 147 167 throw new IllegalArgumentException("Note to reopen must be in layer"); 148 168 } … … 165 185 JosmUserIdentityManager userMgr = JosmUserIdentityManager.getInstance(); 166 186 return User.createOsmUser(userMgr.getUserId(), userMgr.getUserName()); 167 187 } 188 189 /** 190 * Updates notes with new state. Primarily to be used when updating the 191 * note layer after uploading note changes to the server. 192 * @param updatedNotes Map containing the original note as the key and the updated note as the value 193 */ 194 public synchronized void updateNotes(Map<Note, Note> updatedNotes) { 195 for (Map.Entry<Note, Note> entry : updatedNotes.entrySet()) { 196 Note oldNote = entry.getKey(); 197 Note newNote = entry.getValue(); 198 oldNote.updateWith(newNote); 199 } 200 dataUpdated(); 201 } 168 202 } -
src/org/openstreetmap/josm/gui/dialogs/NoteDialog.java
27 27 import javax.swing.event.ListSelectionListener; 28 28 29 29 import org.openstreetmap.josm.Main; 30 import org.openstreetmap.josm.actions.UploadNotesAction; 30 31 import org.openstreetmap.josm.actions.mapmode.AddNoteAction; 31 32 import org.openstreetmap.josm.data.notes.Note; 32 33 import org.openstreetmap.josm.data.notes.Note.State; … … 72 73 private final CloseAction closeAction; 73 74 private final NewAction newAction; 74 75 private final ReopenAction reopenAction; 76 private final UploadNotesAction uploadAction; 75 77 76 78 private NoteData noteData; 77 79 … … 84 86 closeAction = new CloseAction(); 85 87 newAction = new NewAction(); 86 88 reopenAction = new ReopenAction(); 89 uploadAction = new UploadNotesAction(); 87 90 buildDialog(); 88 91 } 89 92 … … 113 116 new SideButton(newAction, false), 114 117 new SideButton(addCommentAction, false), 115 118 new SideButton(closeAction, false), 116 new SideButton(reopenAction, false)})); 119 new SideButton(reopenAction, false), 120 new SideButton(uploadAction, false)})); 117 121 updateButtonStates(); 118 122 } 119 123 … … 131 135 addCommentAction.setEnabled(false); 132 136 reopenAction.setEnabled(true); 133 137 } 138 if(noteData == null || !noteData.isModified()) { 139 uploadAction.setEnabled(false); 140 } else { 141 uploadAction.setEnabled(true); 142 } 134 143 } 135 144 136 145 @Override -
src/org/openstreetmap/josm/gui/layer/NoteLayer.java
72 72 73 73 @Override 74 74 public boolean isModified() { 75 for (Note note : noteData.getNotes()) { 76 if (note.getId() < 0) { //notes with negative IDs are new 77 return true; 78 } 79 for (NoteComment comment : note.getComments()) { 80 if (comment.getIsNew()) { 81 return true; 82 } 83 } 84 } 85 return false; 75 return noteData.isModified(); 86 76 } 87 77 88 78 @Override
