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.PleaseWaitRunnable;
022import org.openstreetmap.josm.gui.io.CloseChangesetDialog;
023import org.openstreetmap.josm.gui.io.CloseChangesetTask;
024import org.openstreetmap.josm.io.ChangesetQuery;
025import org.openstreetmap.josm.io.OnlineResource;
026import org.openstreetmap.josm.io.OsmServerChangesetReader;
027import org.openstreetmap.josm.io.OsmServerUserInfoReader;
028import org.openstreetmap.josm.io.OsmTransferException;
029import org.openstreetmap.josm.tools.Shortcut;
030import org.xml.sax.SAXException;
031
032public class CloseChangesetAction extends JosmAction {
033
034    /**
035     * Constructs a new {@code CloseChangesetAction}.
036     */
037    public CloseChangesetAction() {
038        super(tr("Close open changesets"),
039            "closechangeset",
040            tr("Closes open changesets"),
041            Shortcut.registerShortcut("system:closechangeset",
042                tr("File: {0}", tr("Closes open changesets")),
043                KeyEvent.VK_Q, Shortcut.ALT_CTRL),
044            true
045        );
046        putValue("help", ht("/Action/CloseChangeset"));
047        setEnabled(!Main.isOffline(OnlineResource.OSM_API));
048
049    }
050
051    @Override
052    public void actionPerformed(ActionEvent e) {
053        Main.worker.submit(new DownloadOpenChangesetsTask());
054    }
055
056    protected void onPostDownloadOpenChangesets() {
057        List<Changeset> openChangesets = ChangesetCache.getInstance().getOpenChangesets();
058        if (openChangesets.isEmpty()) {
059            JOptionPane.showMessageDialog(
060                    Main.parent,
061                    tr("There are no open changesets"),
062                    tr("No open changesets"),
063                    JOptionPane.INFORMATION_MESSAGE
064            );
065            return;
066        }
067
068        CloseChangesetDialog dialog = new CloseChangesetDialog();
069        dialog.setChangesets(openChangesets);
070        dialog.setVisible(true);
071        if (dialog.isCanceled())
072            return;
073
074        Collection<Changeset> changesetsToClose = dialog.getSelectedChangesets();
075        CloseChangesetTask closeChangesetTask = new CloseChangesetTask(changesetsToClose);
076        Main.worker.submit(closeChangesetTask);
077    }
078
079    private final class DownloadOpenChangesetsTask extends PleaseWaitRunnable {
080
081        private boolean canceled;
082        private OsmServerChangesetReader reader;
083        private List<Changeset> changesets;
084        private Exception lastException;
085        private UserInfo userInfo;
086
087        private DownloadOpenChangesetsTask() {
088            super(tr("Downloading open changesets ..."), false /* don't ignore exceptions */);
089        }
090
091        @Override
092        protected void cancel() {
093            this.canceled = true;
094            reader.cancel();
095        }
096
097        @Override
098        protected void finish() {
099            SwingUtilities.invokeLater(
100                    new Runnable() {
101                        @Override
102                        public void run() {
103                            if (lastException != null) {
104                                ExceptionDialogUtil.explainException(lastException);
105                            }
106                            ChangesetCache.getInstance().update(changesets);
107                            if (!canceled && lastException == null) {
108                                onPostDownloadOpenChangesets();
109                            }
110                        }
111                    }
112            );
113        }
114
115        /**
116         * Fetch the user info from the server. This is necessary if we don't know
117         * the users id yet
118         *
119         * @return the user info
120         * @throws OsmTransferException in case of any communication exception
121         */
122        protected UserInfo fetchUserInfo() throws OsmTransferException {
123            OsmServerUserInfoReader reader = new OsmServerUserInfoReader();
124            return reader.fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false));
125        }
126
127        @Override
128        protected void realRun() throws SAXException, IOException, OsmTransferException {
129            try {
130                userInfo = fetchUserInfo();
131                if (canceled)
132                    return;
133                reader = new OsmServerChangesetReader();
134                ChangesetQuery query = new ChangesetQuery().forUser(userInfo.getId()).beingOpen(true);
135                changesets = reader.queryChangesets(
136                        query,
137                        getProgressMonitor().createSubTaskMonitor(1, false /* not internal */)
138                );
139            } catch (Exception e) {
140                if (canceled)
141                    return;
142                lastException = e;
143            }
144        }
145
146        public boolean isCanceled() {
147            return canceled;
148        }
149
150        public Exception getLastException() {
151            return lastException;
152        }
153    }
154}