// License: GPL. For details, see LICENSE file.
package reverter;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.util.List;
import java.util.concurrent.Callable;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.command.Command;
import org.openstreetmap.josm.command.conflict.ConflictAddCommand;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.gui.PleaseWaitRunnable;
import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.io.OsmTransferException;
import reverter.ChangesetReverter.RevertType;
public class RevertChangesetTask extends PleaseWaitRunnable {
private final int changesetId;
private final RevertType revertType;
private final boolean newLayer;
private ChangesetReverter rev;
private boolean downloadConfirmed;
public RevertChangesetTask(int changesetId, RevertType revertType) {
this(changesetId, revertType, false);
}
public RevertChangesetTask(int changesetId, RevertType revertType, boolean autoConfirmDownload) {
this(changesetId, revertType, autoConfirmDownload, false);
}
public RevertChangesetTask(int changesetId, RevertType revertType, boolean autoConfirmDownload, boolean newLayer) {
super(tr("Reverting..."));
this.changesetId = changesetId;
this.revertType = revertType;
this.downloadConfirmed = autoConfirmDownload;
this.newLayer = newLayer;
}
private boolean checkAndDownloadMissing() throws OsmTransferException {
if (!rev.hasMissingObjects()) return true;
if (!downloadConfirmed) {
final Integer selectedOption = GuiHelper.runInEDTAndWaitAndReturn(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return JOptionPane.showConfirmDialog(Main.parent,
tr("This changeset has objects that are not present in current dataset.\n" +
"It is needed to download them before reverting. Do you want to continue?"),
tr("Confirm"), JOptionPane.YES_NO_OPTION);
}
});
downloadConfirmed = selectedOption != null && selectedOption == JOptionPane.YES_OPTION;
if (!downloadConfirmed) return false;
}
final PleaseWaitProgressMonitor monitor =
new PleaseWaitProgressMonitor(tr("Fetching missing primitives"));
try {
rev.downloadMissingPrimitives(monitor);
} finally {
monitor.close();
}
return !monitor.isCanceled();
}
@Override
protected void realRun() throws OsmTransferException {
progressMonitor.indeterminateSubTask(tr("Downloading changeset"));
try {
rev = new ChangesetReverter(changesetId, revertType, newLayer,
progressMonitor.createSubTaskMonitor(0, true));
} catch (final RevertRedactedChangesetException e) {
GuiHelper.runInEDT(new Runnable() {
@Override
public void run() {
new Notification(
e.getMessage()+"<br>"+
tr("See {0}", "<a href=\"https://www.openstreetmap.org/redactions\">https://www.openstreetmap.org/redactions</a>"))
.setIcon(JOptionPane.ERROR_MESSAGE)
.setDuration(Notification.TIME_LONG)
.show();
}
});
progressMonitor.cancel();
}
if (progressMonitor.isCanceled()) return;
// Check missing objects
rev.checkMissingCreated();
rev.checkMissingUpdated();
if (rev.hasMissingObjects()) {
// If missing created or updated objects, ask user
rev.checkMissingDeleted();
if (!checkAndDownloadMissing()) return;
} else {
// Don't ask user to download primitives going to be undeleted
rev.checkMissingDeleted();
rev.downloadMissingPrimitives(progressMonitor.createSubTaskMonitor(0, false));
}
if (progressMonitor.isCanceled()) return;
rev.downloadObjectsHistory(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
if (progressMonitor.isCanceled()) return;
if (!checkAndDownloadMissing()) return;
rev.fixNodesWithoutCoordinates(progressMonitor);
List<Command> cmds = rev.getCommands();
final Command cmd = new RevertChangesetCommand(tr(revertType == RevertType.FULL ? "Revert changeset #{0}" :
"Partially revert changeset #{0}", changesetId), cmds);
int n = 0;
for (Command c : cmds) {
if (c instanceof ConflictAddCommand) {
n++;
}
}
final int newConflicts = n;
GuiHelper.runInEDT(new Runnable() {
@Override
public void run() {
Main.main.undoRedo.add(cmd);
if (newConflicts > 0) {
Main.map.conflictDialog.warnNumNewConflicts(newConflicts);
}
}
});
}
@Override
protected void cancel() {
}
@Override
protected void finish() {
}
}