001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005import static org.openstreetmap.josm.tools.I18n.trn;
006
007import java.io.IOException;
008import java.io.InputStream;
009import java.text.MessageFormat;
010import java.util.ArrayList;
011import java.util.Collection;
012import java.util.Collections;
013import java.util.List;
014
015import org.openstreetmap.josm.Main;
016import org.openstreetmap.josm.data.osm.Changeset;
017import org.openstreetmap.josm.data.osm.ChangesetDataSet;
018import org.openstreetmap.josm.data.osm.DataSet;
019import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
020import org.openstreetmap.josm.gui.progress.ProgressMonitor;
021import org.openstreetmap.josm.tools.CheckParameterUtil;
022import org.openstreetmap.josm.tools.XmlParsingException;
023
024/**
025 * Reads the history of an {@link org.openstreetmap.josm.data.osm.OsmPrimitive} from the OSM API server.
026 *
027 */
028public class OsmServerChangesetReader extends OsmServerReader {
029
030    /**
031     * constructor
032     *
033     */
034    public OsmServerChangesetReader(){
035        setDoAuthenticate(false);
036    }
037
038    /**
039     * don't use - not implemented!
040     *
041     */
042    @Override
043    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
044        return null;
045    }
046
047    /**
048     * Queries a list
049     * @param query  the query specification. Must not be null.
050     * @param monitor a progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null
051     * @return the list of changesets read from the server
052     * @throws IllegalArgumentException thrown if query is null
053     * @throws OsmTransferException thrown if something goes wrong w
054     */
055    public List<Changeset> queryChangesets(ChangesetQuery query, ProgressMonitor monitor) throws OsmTransferException {
056        CheckParameterUtil.ensureParameterNotNull(query, "query");
057        List<Changeset> result = null;
058        if (monitor == null) {
059            monitor = NullProgressMonitor.INSTANCE;
060        }
061        try {
062            monitor.beginTask(tr("Reading changesets..."));
063            StringBuilder sb = new StringBuilder();
064            sb.append("changesets?").append(query.getQueryString());
065            try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) {
066                if (in == null)
067                    return null;
068                monitor.indeterminateSubTask(tr("Downloading changesets ..."));
069                result = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true));
070            } catch (IOException e) {
071                Main.warn(e);
072            }
073        } catch(OsmTransferException e) {
074            throw e;
075        } catch(IllegalDataException e) {
076            throw new OsmTransferException(e);
077        } finally {
078            monitor.finishTask();
079        }
080        return result;
081    }
082
083    /**
084     * Reads the changeset with id <code>id</code> from the server
085     *
086     * @param id  the changeset id. id &gt; 0 required.
087     * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null
088     * @return the changeset read
089     * @throws OsmTransferException thrown if something goes wrong
090     * @throws IllegalArgumentException if id &lt;= 0
091     */
092    public Changeset readChangeset(long id, ProgressMonitor monitor) throws OsmTransferException {
093        if (id <= 0)
094            throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0 expected. Got ''{1}''.", "id", id));
095        if (monitor == null) {
096            monitor = NullProgressMonitor.INSTANCE;
097        }
098        Changeset result = null;
099        try {
100            monitor.beginTask(tr("Reading changeset {0} ...",id));
101            StringBuilder sb = new StringBuilder();
102            sb.append("changeset/").append(id);
103            try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) {
104                if (in == null)
105                    return null;
106                monitor.indeterminateSubTask(tr("Downloading changeset {0} ...", id));
107                List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true));
108                if (changesets == null || changesets.isEmpty())
109                    return null;
110                result = changesets.get(0);
111            } catch (IOException e) {
112                Main.warn(e);
113            }
114        } catch(OsmTransferException e) {
115            throw e;
116        } catch(IllegalDataException e) {
117            throw new OsmTransferException(e);
118        } finally {
119            monitor.finishTask();
120        }
121        return result;
122    }
123
124    /**
125     * Reads the changeset with id <code>id</code> from the server
126     *
127     * @param ids  the list of ids. Ignored if null. Only load changesets for ids &gt; 0.
128     * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null
129     * @return the changeset read
130     * @throws OsmTransferException thrown if something goes wrong
131     * @throws IllegalArgumentException if id &lt;= 0
132     */
133    public List<Changeset> readChangesets(Collection<Integer> ids, ProgressMonitor monitor) throws OsmTransferException {
134        if (ids == null)
135            return Collections.emptyList();
136        if (monitor == null) {
137            monitor = NullProgressMonitor.INSTANCE;
138        }
139        try {
140            monitor.beginTask(trn("Downloading {0} changeset ...", "Downloading {0} changesets ...",ids.size(),ids.size()));
141            monitor.setTicksCount(ids.size());
142            List<Changeset> ret = new ArrayList<>();
143            int i=0;
144            for (int id : ids) {
145                if (id <= 0) {
146                    continue;
147                }
148                i++;
149                StringBuilder sb = new StringBuilder();
150                sb.append("changeset/").append(id);
151                try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) {
152                    if (in == null)
153                        return null;
154                    monitor.indeterminateSubTask(tr("({0}/{1}) Downloading changeset {2} ...", i, ids.size(), id));
155                    List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true));
156                    if (changesets == null || changesets.isEmpty()) {
157                        continue;
158                    }
159                    ret.addAll(changesets);
160                } catch (IOException e) {
161                    Main.warn(e);
162                }
163                monitor.worked(1);
164            }
165            return ret;
166        } catch(OsmTransferException e) {
167            throw e;
168        } catch(IllegalDataException e) {
169            throw new OsmTransferException(e);
170        } finally {
171            monitor.finishTask();
172        }
173    }
174
175    /**
176     * Downloads the content of a changeset
177     *
178     * @param id the changeset id. &gt; 0 required.
179     * @param monitor the progress monitor. {@link NullProgressMonitor#INSTANCE} assumed if null.
180     * @return the changeset content
181     * @throws IllegalArgumentException thrown if id &lt;= 0
182     * @throws OsmTransferException thrown if something went wrong
183     */
184    public ChangesetDataSet downloadChangeset(int id, ProgressMonitor monitor) throws IllegalArgumentException, OsmTransferException {
185        if (id <= 0)
186            throw new IllegalArgumentException(MessageFormat.format("Expected value of type integer > 0 for parameter ''{0}'', got {1}", "id", id));
187        if (monitor == null) {
188            monitor = NullProgressMonitor.INSTANCE;
189        }
190        ChangesetDataSet result = null;
191        try {
192            monitor.beginTask(tr("Downloading changeset content"));
193            StringBuilder sb = new StringBuilder();
194            sb.append("changeset/").append(id).append("/download");
195            try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) {
196                if (in == null)
197                    return null;
198                monitor.setCustomText(tr("Downloading content for changeset {0} ...", id));
199                OsmChangesetContentParser parser = new OsmChangesetContentParser(in);
200                result = parser.parse(monitor.createSubTaskMonitor(1, true));
201            } catch (IOException e) {
202                Main.warn(e);
203            }
204        } catch(XmlParsingException e) {
205            throw new OsmTransferException(e);
206        } finally {
207            monitor.finishTask();
208        }
209        return result;
210    }
211}