// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.actions.upload;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.notes.Note;
import org.openstreetmap.josm.data.notes.NoteComment;
import org.openstreetmap.josm.data.osm.NoteData;
import org.openstreetmap.josm.gui.ExceptionDialogUtil;
import org.openstreetmap.josm.gui.PleaseWaitRunnable;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.io.OsmApi;
import org.openstreetmap.josm.io.OsmTransferException;
import org.xml.sax.SAXException;
/**
* Class for uploading note changes to the server
*/
public class UploadNotesTask {
private NoteData noteData;
/**
* Upload notes with modifications to the server
* @param noteData Note dataset with changes to upload
* @param progressMonitor progress monitor for user feedback
*/
public void uploadNotes(NoteData noteData, ProgressMonitor progressMonitor) {
this.noteData = noteData;
Main.worker.submit(new UploadTask(tr("Uploading modified notes"), progressMonitor));
}
private class UploadTask extends PleaseWaitRunnable {
private boolean isCanceled;
private final Map<Note, Note> updatedNotes = new HashMap<>();
private final Map<Note, Exception> failedNotes = new HashMap<>();
/**
* Constructs a new {@code UploadTask}.
* @param title message for the user
* @param monitor progress monitor
*/
UploadTask(String title, ProgressMonitor monitor) {
super(title, monitor, false);
}
@Override
protected void cancel() {
if (Main.isDebugEnabled()) {
Main.debug("note upload canceled");
}
isCanceled = true;
}
@Override
protected void realRun() throws SAXException, IOException, OsmTransferException {
ProgressMonitor monitor = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
OsmApi api = OsmApi.getOsmApi();
for (Note note : noteData.getNotes()) {
if (isCanceled) {
Main.info("Note upload interrupted by user");
break;
}
for (NoteComment comment : note.getComments()) {
if (comment.isNew()) {
if (Main.isDebugEnabled()) {
Main.debug("found note change to upload");
}
processNoteComment(monitor, api, note, comment);
}
}
}
}
private void processNoteComment(ProgressMonitor monitor, OsmApi api, Note note, NoteComment comment) {
try {
if (updatedNotes.containsKey(note)) {
// if note has been created earlier in this task, obtain its real id and not use the placeholder id
note = updatedNotes.get(note);
}
Note newNote;
switch (comment.getNoteAction()) {
case OPENED:
if (Main.isDebugEnabled()) {
Main.debug("opening new note");
}
newNote = api.createNote(note.getLatLon(), comment.getText(), monitor);
break;
case CLOSED:
if (Main.isDebugEnabled()) {
Main.debug("closing note " + note.getId());
}
newNote = api.closeNote(note, comment.getText(), monitor);
break;
case COMMENTED:
if (Main.isDebugEnabled()) {
Main.debug("adding comment to note " + note.getId());
}
newNote = api.addCommentToNote(note, comment.getText(), monitor);
break;
case REOPENED:
if (Main.isDebugEnabled()) {
Main.debug("reopening note " + note.getId());
}
newNote = api.reopenNote(note, comment.getText(), monitor);
break;
default:
newNote = null;
}
updatedNotes.put(note, newNote);
} catch (OsmTransferException e) {
Main.error("Failed to upload note to server: " + note.getId());
Main.error(e);
failedNotes.put(note, e);
}
}
/** Updates the note layer with uploaded notes and notifies the user of any upload failures */
@Override
protected void finish() {
if (Main.isDebugEnabled()) {
Main.debug("finish called in notes upload task. Notes to update: " + updatedNotes.size());
}
noteData.updateNotes(updatedNotes);
if (!failedNotes.isEmpty()) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<Note, Exception> entry : failedNotes.entrySet()) {
sb.append(tr("Note {0} failed: {1}", entry.getKey().getId(), entry.getValue().getMessage()));
sb.append('\n');
}
Main.error("Notes failed to upload: " + sb.toString());
JOptionPane.showMessageDialog(Main.map, sb.toString(), tr("Notes failed to upload"), JOptionPane.ERROR_MESSAGE);
ExceptionDialogUtil.explainException(failedNotes.values().iterator().next());
}
}
}
}