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