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 if query is null 061 * @throws OsmTransferException 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 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 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) 144 throws OsmTransferException { 145 if (ids == null) 146 return Collections.emptyList(); 147 if (monitor == null) { 148 monitor = NullProgressMonitor.INSTANCE; 149 } 150 try { 151 monitor.beginTask(trn("Downloading {0} changeset ...", "Downloading {0} changesets ...", ids.size(), ids.size())); 152 monitor.setTicksCount(ids.size()); 153 List<Changeset> ret = new ArrayList<>(); 154 int i = 0; 155 for (int id : ids) { 156 if (id <= 0) { 157 continue; 158 } 159 i++; 160 try (InputStream in = getChangesetInputStream(id, includeDiscussion, monitor)) { 161 if (in == null) 162 return null; 163 monitor.indeterminateSubTask(tr("({0}/{1}) Downloading changeset {2} ...", i, ids.size(), id)); 164 List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true)); 165 if (changesets == null || changesets.isEmpty()) { 166 continue; 167 } 168 ret.addAll(changesets); 169 } catch (IOException e) { 170 Main.warn(e); 171 } 172 monitor.worked(1); 173 } 174 return ret; 175 } catch (OsmTransferException e) { 176 throw e; 177 } catch (IllegalDataException e) { 178 throw new OsmTransferException(e); 179 } finally { 180 monitor.finishTask(); 181 } 182 } 183 184 /** 185 * Downloads the content of a changeset 186 * 187 * @param id the changeset id. > 0 required. 188 * @param monitor the progress monitor. {@link NullProgressMonitor#INSTANCE} assumed if null. 189 * @return the changeset content 190 * @throws IllegalArgumentException if id <= 0 191 * @throws OsmTransferException if something went wrong 192 */ 193 public ChangesetDataSet downloadChangeset(int id, ProgressMonitor monitor) throws OsmTransferException { 194 if (id <= 0) 195 throw new IllegalArgumentException( 196 MessageFormat.format("Expected value of type integer > 0 for parameter ''{0}'', got {1}", "id", id)); 197 if (monitor == null) { 198 monitor = NullProgressMonitor.INSTANCE; 199 } 200 ChangesetDataSet result = null; 201 try { 202 monitor.beginTask(tr("Downloading changeset content")); 203 StringBuilder sb = new StringBuilder(); 204 sb.append("changeset/").append(id).append("/download"); 205 try (InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true))) { 206 if (in == null) 207 return null; 208 monitor.setCustomText(tr("Downloading content for changeset {0} ...", id)); 209 OsmChangesetContentParser parser = new OsmChangesetContentParser(in); 210 result = parser.parse(monitor.createSubTaskMonitor(1, true)); 211 } catch (IOException e) { 212 Main.warn(e); 213 } 214 } catch (XmlParsingException e) { 215 throw new OsmTransferException(e); 216 } finally { 217 monitor.finishTask(); 218 } 219 return result; 220 } 221}