001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions.upload; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.io.IOException; 007import java.util.HashMap; 008import java.util.Map; 009 010import javax.swing.JOptionPane; 011 012import org.openstreetmap.josm.Main; 013import org.openstreetmap.josm.data.notes.Note; 014import org.openstreetmap.josm.data.notes.NoteComment; 015import org.openstreetmap.josm.data.osm.NoteData; 016import org.openstreetmap.josm.gui.PleaseWaitRunnable; 017import org.openstreetmap.josm.gui.progress.ProgressMonitor; 018import org.openstreetmap.josm.io.OsmApi; 019import org.openstreetmap.josm.io.OsmTransferException; 020import org.xml.sax.SAXException; 021 022/** 023 * Class for uploading note changes to the server 024 */ 025public class UploadNotesTask { 026 027 private UploadTask uploadTask; 028 private NoteData noteData; 029 030 /** 031 * Upload notes with modifications to the server 032 * @param noteData Note dataset with changes to upload 033 * @param progressMonitor progress monitor for user feedback 034 */ 035 public void uploadNotes(NoteData noteData, ProgressMonitor progressMonitor) { 036 this.noteData = noteData; 037 uploadTask = new UploadTask(tr("Uploading modified notes"), progressMonitor); 038 Main.worker.submit(uploadTask); 039 } 040 041 private class UploadTask extends PleaseWaitRunnable { 042 043 private boolean isCanceled = false; 044 Map<Note, Note> updatedNotes = new HashMap<>(); 045 Map<Note, Exception> failedNotes = new HashMap<>(); 046 047 /** 048 * Constructs a new {@code UploadTask}. 049 * @param title message for the user 050 * @param monitor progress monitor 051 */ 052 public UploadTask(String title, ProgressMonitor monitor) { 053 super(title, monitor, false); 054 } 055 056 @Override 057 protected void cancel() { 058 if (Main.isDebugEnabled()) { 059 Main.debug("note upload canceled"); 060 } 061 isCanceled = true; 062 } 063 064 @Override 065 protected void realRun() throws SAXException, IOException, OsmTransferException { 066 ProgressMonitor monitor = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false); 067 OsmApi api = OsmApi.getOsmApi(); 068 for (Note note : noteData.getNotes()) { 069 if(isCanceled) { 070 Main.info("Note upload interrupted by user"); 071 break; 072 } 073 for (NoteComment comment : note.getComments()) { 074 if (comment.getIsNew()) { 075 if (Main.isDebugEnabled()) { 076 Main.debug("found note change to upload"); 077 } 078 processNoteComment(monitor, api, note, comment); 079 } 080 } 081 } 082 } 083 084 private void processNoteComment(ProgressMonitor monitor, OsmApi api, Note note, NoteComment comment) { 085 try { 086 Note newNote; 087 switch (comment.getNoteAction()) { 088 case opened: 089 if (Main.isDebugEnabled()) { 090 Main.debug("opening new note"); 091 } 092 newNote = api.createNote(note.getLatLon(), comment.getText(), monitor); 093 note.setId(newNote.getId()); 094 break; 095 case closed: 096 if (Main.isDebugEnabled()) { 097 Main.debug("closing note " + note.getId()); 098 } 099 newNote = api.closeNote(note, comment.getText(), monitor); 100 break; 101 case commented: 102 if (Main.isDebugEnabled()) { 103 Main.debug("adding comment to note " + note.getId()); 104 } 105 newNote = api.addCommentToNote(note, comment.getText(), monitor); 106 break; 107 case reopened: 108 if (Main.isDebugEnabled()) { 109 Main.debug("reopening note " + note.getId()); 110 } 111 newNote = api.reopenNote(note, comment.getText(), monitor); 112 break; 113 default: 114 newNote = null; 115 } 116 updatedNotes.put(note, newNote); 117 } catch (Exception e) { 118 Main.error("Failed to upload note to server: " + note.getId()); 119 failedNotes.put(note, e); 120 } 121 } 122 123 /** Updates the note layer with uploaded notes and notifies the user of any upload failures */ 124 @Override 125 protected void finish() { 126 if (Main.isDebugEnabled()) { 127 Main.debug("finish called in notes upload task. Notes to update: " + updatedNotes.size()); 128 } 129 noteData.updateNotes(updatedNotes); 130 if (!failedNotes.isEmpty()) { 131 Main.error("Some notes failed to upload"); 132 StringBuilder sb = new StringBuilder(); 133 for (Map.Entry<Note, Exception> entry : failedNotes.entrySet()) { 134 sb.append(tr("Note {0} failed: {1}", entry.getKey().getId(), entry.getValue().getMessage())); 135 sb.append("\n"); 136 } 137 Main.error("Notes failed to upload: " + sb.toString()); 138 JOptionPane.showMessageDialog(Main.map, sb.toString(), tr("Notes failed to upload"), JOptionPane.ERROR_MESSAGE); 139 } 140 } 141 142 } 143 144}