001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.event.ActionEvent; 008import java.awt.event.KeyEvent; 009import java.io.IOException; 010import java.util.Collection; 011import java.util.List; 012 013import javax.swing.JOptionPane; 014import javax.swing.SwingUtilities; 015 016import org.openstreetmap.josm.Main; 017import org.openstreetmap.josm.data.osm.Changeset; 018import org.openstreetmap.josm.data.osm.ChangesetCache; 019import org.openstreetmap.josm.data.osm.UserInfo; 020import org.openstreetmap.josm.gui.ExceptionDialogUtil; 021import org.openstreetmap.josm.gui.MainApplication; 022import org.openstreetmap.josm.gui.PleaseWaitRunnable; 023import org.openstreetmap.josm.gui.io.CloseChangesetDialog; 024import org.openstreetmap.josm.gui.io.CloseChangesetTask; 025import org.openstreetmap.josm.io.ChangesetQuery; 026import org.openstreetmap.josm.io.OnlineResource; 027import org.openstreetmap.josm.io.OsmServerChangesetReader; 028import org.openstreetmap.josm.io.OsmServerUserInfoReader; 029import org.openstreetmap.josm.io.OsmTransferException; 030import org.openstreetmap.josm.tools.Shortcut; 031import org.xml.sax.SAXException; 032 033/** 034 * User action to close open changesets. 035 * 036 * The list of open changesets will be downloaded from the server and presented 037 * to the user. 038 */ 039public class CloseChangesetAction extends JosmAction { 040 041 /** 042 * Constructs a new {@code CloseChangesetAction}. 043 */ 044 public CloseChangesetAction() { 045 super(tr("Close open changesets"), 046 "closechangeset", 047 tr("Close open changesets"), 048 Shortcut.registerShortcut("system:closechangeset", 049 tr("File: {0}", tr("Close open changesets")), 050 KeyEvent.VK_Q, Shortcut.ALT_CTRL), 051 true 052 ); 053 putValue("help", ht("/Action/CloseChangeset")); 054 setEnabled(!Main.isOffline(OnlineResource.OSM_API)); 055 056 } 057 058 @Override 059 public void actionPerformed(ActionEvent e) { 060 MainApplication.worker.submit(new DownloadOpenChangesetsTask()); 061 } 062 063 protected void onPostDownloadOpenChangesets() { 064 List<Changeset> openChangesets = ChangesetCache.getInstance().getOpenChangesetsForCurrentUser(); 065 if (openChangesets.isEmpty()) { 066 JOptionPane.showMessageDialog( 067 Main.parent, 068 tr("There are no open changesets"), 069 tr("No open changesets"), 070 JOptionPane.INFORMATION_MESSAGE 071 ); 072 return; 073 } 074 075 CloseChangesetDialog dialog = new CloseChangesetDialog(); 076 dialog.setChangesets(openChangesets); 077 dialog.setVisible(true); 078 if (dialog.isCanceled()) 079 return; 080 081 Collection<Changeset> changesetsToClose = dialog.getSelectedChangesets(); 082 CloseChangesetTask closeChangesetTask = new CloseChangesetTask(changesetsToClose); 083 MainApplication.worker.submit(closeChangesetTask); 084 } 085 086 private final class DownloadOpenChangesetsTask extends PleaseWaitRunnable { 087 088 private boolean canceled; 089 private OsmServerChangesetReader reader; 090 private List<Changeset> changesets; 091 private Exception lastException; 092 093 private DownloadOpenChangesetsTask() { 094 super(tr("Downloading open changesets ..."), false /* don't ignore exceptions */); 095 } 096 097 @Override 098 protected void cancel() { 099 this.canceled = true; 100 reader.cancel(); 101 } 102 103 @Override 104 protected void finish() { 105 SwingUtilities.invokeLater(() -> { 106 if (lastException != null) { 107 ExceptionDialogUtil.explainException(lastException); 108 } 109 ChangesetCache.getInstance().update(changesets); 110 if (!canceled && lastException == null) { 111 onPostDownloadOpenChangesets(); 112 } 113 }); 114 } 115 116 /** 117 * Fetch the user info from the server. This is necessary if we don't know the users id yet 118 * 119 * @return the user info 120 * @throws OsmTransferException in case of any communication exception 121 */ 122 private UserInfo fetchUserInfo() throws OsmTransferException { 123 return new OsmServerUserInfoReader().fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false)); 124 } 125 126 @Override 127 protected void realRun() throws SAXException, IOException, OsmTransferException { 128 try { 129 UserInfo userInfo = fetchUserInfo(); 130 if (canceled) 131 return; 132 reader = new OsmServerChangesetReader(); 133 ChangesetQuery query = new ChangesetQuery().forUser(userInfo.getId()).beingOpen(true); 134 changesets = reader.queryChangesets( 135 query, 136 getProgressMonitor().createSubTaskMonitor(1, false /* not internal */) 137 ); 138 } catch (OsmTransferException | IllegalArgumentException e) { 139 if (canceled) 140 return; 141 lastException = e; 142 } 143 } 144 145 /** 146 * Determines if the download task has been canceled. 147 * @return {@code true} if the download task has been canceled 148 */ 149 public boolean isCanceled() { 150 return canceled; 151 } 152 153 /** 154 * Returns the last exception that occured. 155 * @return the last exception that occured, or {@code null} 156 */ 157 public Exception getLastException() { 158 return lastException; 159 } 160 } 161}