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 * Constructs a new {@code OsmServerChangesetReader}. 032 */ 033 public OsmServerChangesetReader() { 034 setDoAuthenticate(false); 035 } 036 037 /** 038 * don't use - not implemented! 039 */ 040 @Override 041 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException { 042 return null; 043 } 044 045 protected final InputStream getChangesetInputStream(long id, boolean includeDiscussion, ProgressMonitor monitor) 046 throws OsmTransferException { 047 StringBuilder sb = new StringBuilder(); 048 sb.append("changeset/").append(id); 049 if (includeDiscussion) { 050 sb.append("?include_discussion=true"); 051 } 052 return getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true)); 053 } 054 055 /** 056 * Queries a list 057 * @param query the query specification. Must not be null. 058 * @param monitor a progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 059 * @return the list of changesets read from the server 060 * @throws IllegalArgumentException thrown if query is null 061 * @throws OsmTransferException thrown if something goes wrong w 062 */ 063 public List<Changeset> queryChangesets(ChangesetQuery query, ProgressMonitor monitor) throws OsmTransferException { 064 CheckParameterUtil.ensureParameterNotNull(query, "query"); 065 List<Changeset> result = null; 066 if (monitor == null) { 067 monitor = NullProgressMonitor.INSTANCE; 068 } 069 try { 070 monitor.beginTask(tr("Reading changesets...")); 071 StringBuilder sb = new StringBuilder(); 072 sb.append("changesets?").append(query.getQueryString()); 073 try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) { 074 if (in == null) 075 return null; 076 monitor.indeterminateSubTask(tr("Downloading changesets ...")); 077 result = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 078 } catch (IOException e) { 079 Main.warn(e); 080 } 081 } catch(OsmTransferException e) { 082 throw e; 083 } catch(IllegalDataException e) { 084 throw new OsmTransferException(e); 085 } finally { 086 monitor.finishTask(); 087 } 088 return result; 089 } 090 091 /** 092 * Reads the changeset with id <code>id</code> from the server. 093 * 094 * @param id the changeset id. id > 0 required. 095 * @param includeDiscussion determines if discussion comments must be downloaded or not 096 * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 097 * @return the changeset read 098 * @throws OsmTransferException thrown if something goes wrong 099 * @throws IllegalArgumentException if id <= 0 100 * @since 7704 101 */ 102 public Changeset readChangeset(long id, boolean includeDiscussion, ProgressMonitor monitor) throws OsmTransferException { 103 if (id <= 0) 104 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0 expected. Got ''{1}''.", "id", id)); 105 if (monitor == null) { 106 monitor = NullProgressMonitor.INSTANCE; 107 } 108 Changeset result = null; 109 try { 110 monitor.beginTask(tr("Reading changeset {0} ...",id)); 111 try (InputStream in = getChangesetInputStream(id, includeDiscussion, monitor)) { 112 if (in == null) 113 return null; 114 monitor.indeterminateSubTask(tr("Downloading changeset {0} ...", id)); 115 List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 116 if (changesets == null || changesets.isEmpty()) 117 return null; 118 result = changesets.get(0); 119 } catch (IOException e) { 120 Main.warn(e); 121 } 122 } catch(OsmTransferException e) { 123 throw e; 124 } catch(IllegalDataException e) { 125 throw new OsmTransferException(e); 126 } finally { 127 monitor.finishTask(); 128 } 129 return result; 130 } 131 132 /** 133 * Reads the changesets with id <code>ids</code> from the server. 134 * 135 * @param ids the list of ids. Ignored if null. Only load changesets for ids > 0. 136 * @param includeDiscussion determines if discussion comments must be downloaded or not 137 * @param monitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 138 * @return the changeset read 139 * @throws OsmTransferException thrown if something goes wrong 140 * @throws IllegalArgumentException if id <= 0 141 * @since 7704 142 */ 143 public List<Changeset> readChangesets(Collection<Integer> ids, boolean includeDiscussion, ProgressMonitor monitor) throws OsmTransferException { 144 if (ids == null) 145 return Collections.emptyList(); 146 if (monitor == null) { 147 monitor = NullProgressMonitor.INSTANCE; 148 } 149 try { 150 monitor.beginTask(trn("Downloading {0} changeset ...", "Downloading {0} changesets ...",ids.size(),ids.size())); 151 monitor.setTicksCount(ids.size()); 152 List<Changeset> ret = new ArrayList<>(); 153 int i=0; 154 for (int id : ids) { 155 if (id <= 0) { 156 continue; 157 } 158 i++; 159 try (InputStream in = getChangesetInputStream(id, includeDiscussion, monitor)) { 160 if (in == null) 161 return null; 162 monitor.indeterminateSubTask(tr("({0}/{1}) Downloading changeset {2} ...", i, ids.size(), id)); 163 List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 164 if (changesets == null || changesets.isEmpty()) { 165 continue; 166 } 167 ret.addAll(changesets); 168 } catch (IOException e) { 169 Main.warn(e); 170 } 171 monitor.worked(1); 172 } 173 return ret; 174 } catch(OsmTransferException e) { 175 throw e; 176 } catch(IllegalDataException e) { 177 throw new OsmTransferException(e); 178 } finally { 179 monitor.finishTask(); 180 } 181 } 182 183 /** 184 * Downloads the content of a changeset 185 * 186 * @param id the changeset id. > 0 required. 187 * @param monitor the progress monitor. {@link NullProgressMonitor#INSTANCE} assumed if null. 188 * @return the changeset content 189 * @throws IllegalArgumentException thrown if id <= 0 190 * @throws OsmTransferException thrown if something went wrong 191 */ 192 public ChangesetDataSet downloadChangeset(int id, ProgressMonitor monitor) throws IllegalArgumentException, OsmTransferException { 193 if (id <= 0) 194 throw new IllegalArgumentException(MessageFormat.format("Expected value of type integer > 0 for parameter ''{0}'', got {1}", "id", id)); 195 if (monitor == null) { 196 monitor = NullProgressMonitor.INSTANCE; 197 } 198 ChangesetDataSet result = null; 199 try { 200 monitor.beginTask(tr("Downloading changeset content")); 201 StringBuilder sb = new StringBuilder(); 202 sb.append("changeset/").append(id).append("/download"); 203 try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) { 204 if (in == null) 205 return null; 206 monitor.setCustomText(tr("Downloading content for changeset {0} ...", id)); 207 OsmChangesetContentParser parser = new OsmChangesetContentParser(in); 208 result = parser.parse(monitor.createSubTaskMonitor(1, true)); 209 } catch (IOException e) { 210 Main.warn(e); 211 } 212 } catch(XmlParsingException e) { 213 throw new OsmTransferException(e); 214 } finally { 215 monitor.finishTask(); 216 } 217 return result; 218 } 219}