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