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