001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions.downloadtasks;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.io.IOException;
008
009import javax.swing.JOptionPane;
010
011import org.openstreetmap.josm.Main;
012import org.openstreetmap.josm.data.osm.UserInfo;
013import org.openstreetmap.josm.gui.JosmUserIdentityManager;
014import org.openstreetmap.josm.gui.util.GuiHelper;
015import org.openstreetmap.josm.io.ChangesetQuery;
016import org.openstreetmap.josm.io.OsmServerUserInfoReader;
017import org.openstreetmap.josm.io.OsmTransferCanceledException;
018import org.openstreetmap.josm.io.OsmTransferException;
019import org.openstreetmap.josm.tools.CheckParameterUtil;
020import org.openstreetmap.josm.tools.ExceptionUtil;
021import org.xml.sax.SAXException;
022
023/**
024 * Asynchronous task to send a changeset query to the OSM API.
025 * @since 2689
026 */
027public class ChangesetQueryTask extends AbstractChangesetDownloadTask {
028
029    class DownloadTask extends RunnableDownloadTask {
030        /** the changeset query */
031        private ChangesetQuery query;
032        /** the reader object used to read information about the current user from the API */
033        private final OsmServerUserInfoReader userInfoReader = new OsmServerUserInfoReader();
034
035        DownloadTask(Component parent, ChangesetQuery query) {
036            super(parent, tr("Querying and downloading changesets"));
037            this.query = query;
038        }
039
040        /**
041         * Tries to fully identify the current JOSM user
042         *
043         * @throws OsmTransferException if something went wrong
044         */
045        protected void fullyIdentifyCurrentUser() throws OsmTransferException {
046            getProgressMonitor().indeterminateSubTask(tr("Determine user id for current user..."));
047
048            UserInfo info = userInfoReader.fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false));
049            JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
050            im.setFullyIdentified(im.getUserName(), info);
051        }
052
053        @Override
054        protected void realRun() throws SAXException, IOException, OsmTransferException {
055            try {
056                JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
057                if (query.isRestrictedToPartiallyIdentifiedUser() && im.isCurrentUser(query.getUserName())) {
058                    // if we query changesets for the current user, make sure we query against
059                    // its user id, not its user name. If necessary, determine the user id first.
060                    //
061                    if (im.isPartiallyIdentified()) {
062                        fullyIdentifyCurrentUser();
063                    }
064                    query = query.forUser(JosmUserIdentityManager.getInstance().getUserId());
065                }
066                if (isCanceled())
067                    return;
068                getProgressMonitor().indeterminateSubTask(tr("Query and download changesets ..."));
069                downloadedChangesets.addAll(reader.queryChangesets(query, getProgressMonitor().createSubTaskMonitor(0, false)));
070            } catch (OsmTransferCanceledException e) {
071                // thrown if user cancel the authentication dialog
072                setCanceled(true);
073            }  catch (OsmTransferException e) {
074                if (isCanceled())
075                    return;
076                rememberLastException(e);
077            }
078        }
079
080        @Override
081        protected void finish() {
082            rememberDownloadedData(downloadedChangesets);
083            if (isCanceled())
084                return;
085            if (lastException != null) {
086                GuiHelper.runInEDTAndWait(new Runnable() {
087                    private final Component parent = progressMonitor != null ? progressMonitor.getWindowParent() : null;
088                    @Override
089                    public void run() {
090                        JOptionPane.showMessageDialog(
091                                parent != null ? parent : Main.parent,
092                                ExceptionUtil.explainException(lastException),
093                                tr("Errors during download"),
094                                JOptionPane.ERROR_MESSAGE);
095                    }
096                });
097                return;
098            }
099            updateChangesets();
100        }
101
102        @Override
103        protected void cancel() {
104            super.cancel();
105            synchronized (this) {
106                if (userInfoReader != null) {
107                    userInfoReader.cancel();
108                }
109            }
110        }
111    }
112
113    /**
114     * Creates the task.
115     *
116     * @param query the query to submit to the OSM server. Must not be null.
117     * @throws IllegalArgumentException if query is null.
118     */
119    public ChangesetQueryTask(ChangesetQuery query) {
120        this(Main.parent, query);
121    }
122
123    /**
124     * Creates the task.
125     *
126     * @param parent the parent component relative to which the {@link org.openstreetmap.josm.gui.PleaseWaitDialog} is displayed.
127     * Must not be null.
128     * @param query the query to submit to the OSM server. Must not be null.
129     * @throws IllegalArgumentException if query is null.
130     * @throws IllegalArgumentException if parent is null
131     */
132    public ChangesetQueryTask(Component parent, ChangesetQuery query) {
133        CheckParameterUtil.ensureParameterNotNull(query, "query");
134        setDownloadTask(new DownloadTask(parent, query));
135    }
136}